一篇教你轻松解析复杂的指针声明

一、指针运算符及其优先级

指针往往会和一些运算符结合使用,主要包括以下几种:

  • 指针声明:int *。
  • 取址运算符:&。
  • 间接访问运算符:*。
  • 自增自减运算符: ++、--。
  • 成员选择运算符:.、->。
  • 其他运算符: []、()。

这些运算符的优先级按照从高到低的顺序依次为:[]、()、.、->、++、--、*、&。

这里可以分析几个较为简单的指针表达式:

*p++; 先间接访问指针p,然后p的值再自增
&p++; 指针变量的地址自增运算
&stu.name; 结构体成员变量name的地址
int *a[10];

定义一个指针数组,数组元素类型为int *

int (*a)[10]; 定义一个数组指针,指向数组类型int a[10]
int *f (int); 定义一个指针函数,函数返回值为int *
int (*f)(int); 定义一个函数指针,指向函数类型为int f(int)
int *(*f)([10]; 定义一个数组指针,指向数组类型为int *a[10]

二、左右法则

对于复杂的指针声明,我们可以借助“左右法则”来分析。

The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reserved.Once everything in the parantheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.

翻译成中文就是:首先从最里面的圆括号(未定义标识符)看起,先往右看,再往左看,每当遇到圆括号时,就应该调转阅读方向。一旦解析完圆括号里所有东西,就跳出圆括号。重复这个过程,直到整个声明解析完毕。

这里我们根据左右法则再分析几个较为复杂的指针表达式:

int *(*(*f)(int))[10];

 首先从最里面的圆括号看起,(*f)说明了f是一个指针,也给整个表达式定了性,这个语句声明的是一个指针;再往右看(int)是一个参数列表,说明该指针类型是一个函数指针,函数的形参是(int);再往左看,*说明该指针指向的函数返回值是一个指针;此时圆括号已解析完毕,跳出圆括号,往右看是一个数组,说明返回值只一个指向数组的指针,再往左看是int *,即指针数组中的元素类型为int *。这其实等价于int *(*p)[10];

int (*f(int, int))[10];

 首先这是一个函数指针,指向的函数形参为(int,int),返回值为一个数组。

int (*(*f)(int, int))(int);

首先这是一个函数指针,指向的函数形参为(int,int),即指向函数类型为int *f(int, int),其次函数的返回值为一个函数指针,指向一个形参为(int)且返回int的函数,即指向函数类型为int *f(int)

 int (*f)(int *p, int, int (*fp)(int*, int));

首先这是一个函数指针,指向的函数形参为(int *p, int, int (*fp)(int*, int)),函数的返回值为int

 int (*(*f)[10])(int *p);

 首先这是一个数组指针,指向数组类型为int *a[10],其中的元素为int *p类型。

 

 剩下一个可以尝试自行分析一下:

(*(void (*)())0)();

你可能感兴趣的:(C语言进阶,开发语言,c语言)