一. 解读复杂指针声明

右左法则首先从标识符开始阅读,然后往右看,再往左看。每当遇到圆括号时,就应该调转阅读方向。一旦解析完括号里所有的东西,就跳出括号。重复这个过程直到整个声明解析完毕。

 
  
  1. int *a[10] 
  2. // 首先 a 右边是[],说明 a 是一个具有10个元素的数组 
  3. // 其次 a 左边是 int*,说明 a 的元素是 int 类型的指针 
  4.  
  5. int (*a)[10] 
  6. // 首先 a 左边是一个 * 号,说明 a 是一个指针 
  7. // 跳出括号,右边是 [], 说明 a 是一个指向具有10个元素的数组的指针 
  8. // 左边是 int,说明元素的类型是 int 
  9.  
  10. int (*func)(int *p); 
  11. // 首先找到 func,它左边是一个 * 号,这说明 func 是一个指针 
  12. // 然后跳出这个圆括号,先看右边,也是个圆括号,这说明 (*func) 是个函数,而 func 是指向这个函数的指针 
  13. // 这个函数具有 int* 类型的参数,返回值类型为 int 
  14.  
  15. int (*func[5])(int* p) 
  16. // 首先找到 func, 右边是[],说明 func 是一个具有5个元素的数组 
  17. // 其次 func 左边有一个 *,说明 func 的元素是指针,要注意 * 不是修饰func的,而是修饰 func[5]的 
  18. // 跳出这个括号,右边也是一个括号,说明 func 数组的元素是函数类型的指针 

二. 数组首地址 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修饰的是数组的内容,即数组的每个元素。数组在这里没有名子。

 

四. 函数指针 & 指针函数

函数指针:指向函数的指针变量。

指针函数:带指针的函数,也就是返回指针的函数。

 
  
  1. char * fun(char* a, char* b)  //定义为 指针函数   
  2. {......  }   
  3.    
  4. int main()     
  5. {     
  6.   char* (*p)(char* p1, char* p2); //定义为 函数指针     
  7.      
  8.   p = &fun; //把函数地址赋给他     
  9.   //p = fun;  //这样写也行   
  10.    
  11.   (*p)("aa""bb"); //使用函数指针     
  12.      
  13.   return 0;     
  14. }   

五. 指针常量 & 常量指针

 
  
  1. const char* p1; //常量指针,指向常量的指针   
  2. char const* p2;   
  3.    
  4. charconst p3; //指针常量,指针是常量  

怎么记?

a. 可以先把类型名去掉,然后看 const 离谁近,就修饰谁。

b. 也可以const 在 * 左边的为常量指针,const 在 * 右边的为指针常量。

六. 野指针

野指针是怎么造成的?

1. 指针变量被创建而没有初始化。

2. 指针 p 被 free 或者 delete 之后, 没有置为 NULL。