一、C语言声明的优先级规则:
A、声明从变量名字开始读取,然后按照优先级顺序依次读取。
B、优先级从高到低依次是:
B1、声明中被括号括起来的那部分
B2、后缀操作符:
括号()表示这是一个函数
方括号[ ]表明这是一个数组
B3、前缀操作符:星号 * 表示“指向……的指针”
C、如果const和volatile关键字的后面紧跟类型说明符(如int,long等),那么它作用于类型说明符。在其他情况下,const和volatile关键字作用于它左边紧邻的指针星号。(const在 * 号左边,则修饰指针指向的变量,在 * 右边,则修饰指针)
举例:char * const *(*next)();
1、变量名next,它和 * 被括号括住,——>next是一个指向……的指针;
2、看括号外面,有星号 * 前缀 和 ()括号后缀,由B2规则,后缀括号优先级比较高,——>next是一个函数指针,指向一个返回……的函数;
3、前缀 * ,得出指针指向的内容,函数返回一个指针,指针指向一个返回指针的函数;
4、char * const为指向字符的常量指针,故函数的返回值指向一个指向字符的常量指针。
综上:next是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为char的常量指针。
二、也可以用下图来分析优先级
用上图来分析char * const *(*next)();
1、图中第1步,找标识符next——>表示“next是……”;
2、第2/3步,不匹配,next右边既不是方括号,也不是左括号;
3、第4步,不匹配,左边不是左括号;
4、第5步,与*号匹配,表示“指向……的指针”,转第4步,“(”和“)”匹配,转到第2步;
5、第2步,不匹配,不是方括号;
6、第3步,匹配,表示“返回……的函数”
7、第4步,匹配,转到下一步;
8、第5步,匹配*,“指向……的指针”
9、第5步,匹配const,“只读”
10、第5步,匹配*,“指向……的指针”
11、第6步,匹配,表示“char”
这个方法还是不清楚,还是第一个好。
钻钻牛角尖其实也挺好,要不碰到很多数组指针、指针数组、函数指针啥的都分不清。
三、练习
(1)练习一:char *(* c[10])(int **p);
1、标识符c,后面[],c是一个……的数组
2、c[10]前面是个*,c[10]是个数组,每个数组的元素是指向……的指针;
3、(* c[10])后面是括号,指向返回……的函数的指针数组;
4、函数的参数int **p,p是个指向……的指针,*p前的*表明参数是个指向指针的指针,前面的int表明,参数是个是个指针,这个指针指向一个指向int的指针;
5、(* c[10])(int **p)前的*表明函数的返回值是个指针
6、最前面的char,表明函数的返回值是个指向char的指针
综上,c[10]是个指向函数的指针数组,这个函数的返回值是个指向char的指针,这个函数的参数是个指向指向int类型的指针的指针。
参考答案:c是一个数组[0...9],它的元素是函数指针,指针指向的函数的返回值是一个指向char的指针。
(2)练习2:void ( * signal(int sig, void(*func)(int)) )(int)
1、signal(),signal是个函数,void (*signal())(int)
2、*signal(),返回指针的函数,void ( )(int)
3、( )(int),返回……的函数
4、无返回值的函数
综上,signal是个函数,它返回一个函数指针,这个指针指向的函数接受一个int参数,并返回void。
其中参数void(*func)(int),表示func是个指针,指向一个函数,所指向的函数接受一个int参数,返回值是void.
用void ( * signal(int sig, void(*func)(int)) )(int)简化这条语句:
typedef void(*ptr_to_func)(int); //表示ptr_to_func是一个函数指针,指向的函数接受一个int参数,返回值为void
ptr_to_func signal(int, ptr_to_func); //表示signal是一个函数,它接受两个参数,其中一个是int,另一个数ptr_to_func,返回值是ptr_to_func
本文完全是抄的书,一边抄,一边理解