没有内存就没有指针
CPU 只能通过地址来取得内存中的代码和数据,程序在执行过程中会告知 CPU 要执行的代码以及要读写的数据的地址。如果程序不小心出错,或者开发者有意为之,在 CPU 要写入数据时给它一个代码区域的地址,就会发生内存访问错误。这种内存访问错误会被硬件和操作系统拦截,强制程序崩溃,程序员没有挽救的机会。
CPU 访问内存时需要的是地址,而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址。编译和链接过程的一项重要任务就是找到这些名称所对应的地址。
指针的长度由地址总线决定,也就是说CPU的寻址能力。
不要说是字长,字长是根据数据总线决定的。有的机器数据总线和地址总线不一定都是一样的
像现在64位机器中很对地址总线都是32位的
指针运算符 * (常和去地址操作符&一起出现)
- 表示乘法,例如int a = 3, b = 5, c; c = a * b;,这是最容易理解的。
- 表示定义一个指针变量,以和普通变量区分开,例如int a = 100; int *p = &a;。
- 表示获取指针指向的数据,是一种间接操作,例如int a, b, *p = &a; *p = 100; b = *p;
- 指针也有地址,指向指针的指针被称为二级指针,以此类推
数组指针,和指针数组
- 指针数组比较好理解 intp[2];[]优先级高于,所以首先这是个数组,其次数组里面元素的类型是int*
- 数组指针,指向数组的指针(即代表它的基本单位是数组,即运算的步长是一个数组的大小),也叫二维数组指针(当然一维也可以用,但是没有实际意义)
#include <stdio.h>
int main(void) {
int arr2[2][2] = {{1,2},{3,4}};
printf("%x\n",arr2);
int arr1[2] = {1,2};
int (p)[2] = arr2;
printf("%x\n",p);
printf("%d\n",p[0]);
printf("%d",*(++p)[0]);
return 0;
}
输出结果
1908fec0
1908fec0
1
3
可以看到int (*p)[2] = arr2;(数组名弱化成指针,即数组首地址)两者是一致的
p[0]即是数组第一列首地址首个元素arr2[0][0]的地址,取值就是1
p++指向arr2[1],即是数组第二列首地址首个元素arr2[1][0]的地址,取值就是3
void*和NULL
- void*只代表一个地址信息,没有任何类型信息
- void*可以接收任何类型的指针
- void*赋值给别的类型指针(看标准),C++是需要强转的
- NULL不等价于0,虽然有时候一样
- NULL是系统极小的一部分不被使用的地址空间,依操作系统而定