规则
++从名字开始,关键定义都是普通的定义格式,只是定义格式缺少的部分被层层嵌套++。
- 指针:int *p
- 数组: int arr[10]
- 函数指针: int (* p)(int)
- example: int (*p3)[6];
- (*p3): 定义p3指针,但不知道指针类型
- int (*p3)[6]:指针类型为 int [6]的数组,所以p3指针指向一个6个元素的数组
- example:
char *(* c[10])(int **p);
- (* c[10]) : 定义10个元素为指针的数组,指针类型未知。
char *(* c[10])(int **p);
:该指针类型为char *(* p1)(int **p);
- example
1
2//定义一个含4个元素数组的指针,每个元素为 函数的指针,该函数参数为 一个含10个元素的数组的引用 返回值为 含10个元素的数组的指针
int (*(*getCA[4])(int(&)[10]))[10];
C语言标准规定,对于一个符号的定义,编译器总是从它的名字开始读取,然后按照优先级顺序依次解析。从名字开始,不是从开头也不是从末尾,这是理解复杂指针的关键!
它们的优先级从高到低依次是:
() [] *(右结合性)
- 前缀递增递减
++p
和*
优先级相同,从右到左; - 后缀递增递减
p++
比前缀++p
优先级高,从左到右。
- 前缀递增递减
定义中被括号( )括起来的那部分。
后缀操作符:括号( )表示这是一个函数,方括号[ ]表示这是一个数组。
前缀操作符:星号*表示“指向xxx的指针”。
例子
1 | int *p1[6]; //指针数组 |
例子详解
1 | char *(* c[10])(int **p); |
char *(* c[10])(int **p);
(* c[10]) 指针数组,数组的每个元素是指针,指针类型未知
[ ]
的优先级高于 *,编译器先解析c[10],c 首先是一个数组,它前面的*表明每个数组元素都是一个指针,只是还不知道指向什么类型的数据。整体上来看,(* c[10])说明 c 是一个指针数组,只是指针指向的数据类型尚未确定。(int **p)
:( )说明是一个函数,int **p是函数参数。跳出括号,根据优先级规则(() 的优先级高于 *)应该先看右边(红色粗体):
char *是函数的返回值类型。
int (*(*(*pfunc)(int *))[5])(int *)
- (*pfunc) 一个指针
(*(*pfunc)(int *))
:根据优先级规则应该先看右边的(int *),它表明这是一个函数,int *是参数列表。再看左边的*,
==它表明函数的返回值是一个指针,只是指针指向的数据类型尚未确定==++(下一步就是定义函数的返回值)++。- 由第二步可知,它表明 pfunc 是一个指向函数的指针,现在函数的参数列表确定了,也知道返回值是一个指针了(只是不知道它指向什么类型的数据)
(*(*(*pfunc)(int *))[5])
:[ ] 的优先级高于 *,先看右边,[5] 表示这是一个数组,再看左边,* 表示数组的每个元素都是指针。也就是说,* [5] 是一个指针数组,
函数返回的指针就指向这样一个数组。- 指针数组中的指针指向原型为int func(int *);的函数。
- 将上面的三部分合起来就是:pfunc 是一个函数指针(蓝色部分),++该函数的返回值是一个指针,它指向一个指针数组(红色部分)++,指针数组中的指针指向原型为int func(int *);的函数(橘黄色部分)。