一. 解读复杂指针声明
右左法则:首先从标识符开始阅读,然后往右看,再往左看。每当遇到圆括号时,就应该调转阅读方向。一旦解析完括号里所有的东西,就跳出括号。重复这个过程直到整个声明解析完毕。
二. 数组首地址 a, &a, &a[0]
以a[10]为例:
1.a作为右值时,代表数组首元素的首地址,而非数组首地址。
也就是 a[0] 的地址。int i = *(a+1),这里a是右值,所是代表首元素的首地址,a+1代表下一个元素的首地址,即&a[1]。
2.a 是整个数组的名子。
所以 sizeof(a) 的值为 size(int) * 10 = 40,代表整个数组的大小。
3.&a即为取 a 的首地址,也即是整个数组的首地址。
所以 sizeof(&a) 的值为 4。
但是在VC6.0里显示的是40,这是不对的。code:block里显示的是4。
int * p = (int*)(&a+1) 中 &a+1 代表下一个数组的首地址,显然是越界的。
4.&a[0]代表首元素的首地址。
所以 sizeof(&a[0]) 的值为 4。
5. &a[10] 很显然,数组越界了,但是他的sizeof是多少呢?
也是4,因为关键字sizeof求值是在编译的时候,虽然并不存在a[10]这个元素,但是这里并没有真正访问a[10],而是根据数组元素的类型来确定其值。所以sizeof(a[10])不会出错。
6. a[-1]代表什么意思?
首先要明白下标的形式被编译器解析成指针的形式,即a[1] 解析成 *(a+1),那么a[-1]就被解析成*(a-1)。
三. 指针数组 & 数组指针
指针数组:首先它是一个数组,数组的元素都是指针,也称为"储存指针的数组"。
数组指针:首先它是一个指针,它指向一个数组。也可以理解为"数组的指针。"
int *p1[10]
int (*p2)[10]各代表什么?要弄清这个问题,首先要知道[ ]优先级比*要高。
p1先与[ ]结合,构成一个数组定义,数组名为p1,int*修饰的是数组的内容,即数组的每个元素。
p2中()的优先级比[ ]高,所以*号先与P2构成一个指针的定义,指针变量名为P2,int修饰的是数组的内容,即数组的每个元素。数组在这里没有名子。
四. 函数指针 & 指针函数
函数指针:指向函数的指针变量。
指针函数:带指针的函数,也就是返回指针的函数。
五. 指针常量 & 常量指针
怎么记?
a. 可以先把类型名去掉,然后看 const 离谁近,就修饰谁。
b. 也可以const 在 * 左边的为常量指针,const 在 * 右边的为指针常量。
六. 野指针
野指针是怎么造成的?
1. 指针变量被创建而没有初始化。
2. 指针 p 被 free 或者 delete 之后, 没有置为 NULL。