内存地址:
1、Cpu是通过内存地址来访问内存数据,cpu与内存条硬件之间有个地址总线,读数据的时候,cpu通过地址总线将需要访问的内存地址告诉内存条,内存条返回数据给cpu。
2、对于cpu而言,内存地址是唯一读写内存的方式。
3、内存地址是一个整数,我们应用程序使用的内存地址不是真实的物理地址,而是操作系统映射好的虚拟内存地址,如果应用程序用的是真实的物理地址,一旦程序有错,整个系统都会崩溃。
地址总线:
1、 地址总线上,每根线有两种状态:0、1
2、 Cpu通过调整地址总线的状态,来告诉内存条需要读写的地址
3、 下图为cpu要访问地址为11001001的数据
取变量地址:
1、 使用取地址&符号
int a = 10;
printf("%d",&a);
指针:存放内存地址的变量
1、 定义: 数据类型 * 变量名称 ----------int* p;
2、 int* p = 123; //指针就是一个变量,可以存放任意整数
3、 本质是一个变量,一个4个字节(32位程序)或者8个字节(64位程序)的整形变量,同样在内存中开辟了空间
4、 NULL是一个值(0),来表示一个非法的地址,是操作系统自有的地址,不允许应用程序来访问
5、 指针是用来存放地址的变量,而地址长度都是一样的,为什么指针却有不同的类型? 因为要通过类型来读取指针变量所对应的值,int类型就读4个字节的内存数据,double类型就读8个字节
int a = 100;
int* p = &a;//将4个字节的变量a的首地址赋值给p
int b = *p; //从p变量存放的首地址开始,读4个字节的值赋给b
6、
int a = 100;
int* p = &a;
//p[0]表示:从p变量存放的首地址开始,读4个字节的值
//p[1]表示:读了4个字节之后,再读4个字节的值,然而这4个字节的值是不确定的
printf("%d,%d",p[0],p[1]);
指针变量只支持加减法(因为内存是连续的,线性的):
int a = 110;
int* p = &a;
p = p + 1;//由于p是int类型,此时加1的话,是移动4个字节
printf("%d,%d", p, *p);
getchar();
void* 只能用来存储地址数据,不能用来取值,因为系统不知道需要取几个字节的数据
数组和指针
int arr[4] = {1,2,3,4};
//1、通过取地址符号,获取数组首元素的地址
int* p1 = &arr[0];
//2、通过数组名:数组名就是首元素的首地址
int* p2 = arr;
printf("%d,%d\n", p1,p2);//打印结果是一样的
//3、利用指针来遍历数组
for (int i = 0; i < 4; i++)
{
printf("%d\n",p2[i]); //打印结果是1,2,3,4
}
for (int i = 0; i < 4; i++)
{
printf("%d\n", *(p2+i)); //打印结果是1,2,3,4
}