在讲右左法则前看一个声明:void(*(func(int,void(*)(int)))(int)
这是一个会让初学者感到非常头疼,感到恐惧的声明,在熟练掌握C/C++的声明语法之前,不学习一定的规则,想理解好这类复杂声明是比较困难的。
1.右左法则
首先从最里面的圆括号开始阅读,首先向右看,再往左看。每当遇到圆括号时,就应该调转阅读方向。一旦解析完圆括号里面所有东西,就跳出圆括号。重复整个过程直到整个声明解析完成。其实左右法则就是以标示符为中心点,自右向左旋转解读指针的声明含义。
例如:
int (*a)[10]; 整型数组指针(首先看括号里面,a是一个指针变量,他存放的是数组元素的地址,而数组的每个元素都是整形)
int (*a[10])(int) 函数指针数组(首先a是一个数组,它的元素都是指针,这个指针指向一个形参为整形,返回值也为整形的函数)
1.首先从最里面的圆括号开始阅读
2.首先向右看,再往左看
3.每当遇到圆括号或者方括号时可以确定部分类型,并调转阅读方向
4.重复2,3的步骤直到阅读结束
2.利用右左法则阅读声明
1.
char * (* (*fun) (int *) [3]);
fun是一个指向函数的指针,指向的函数有一个整形指针的参数,并且函数的返回值是一个指针。返回的指针指向一个数组,指向的数组有3个元素,每个元素都是字符指针类型。
2.
*((void(*)())0)();
该代码是一次函数调用
讲的是先将0强制转换成void(*)()型的函数指针,然后去调用零地址处的函数。
3.
void (* func(char *,void(*)(int,int)))(char,int *);
该代码是一次函数声明,声明的函数的名字叫做func。
func函数的参数有两个,第一个是char*类型,第二个是void(*)型的函数指针类型,该函数指针能够指向的函数的参数有两个int,返回类型是void。
func函数的返回值是一个void(*)型的函数指针,这个函数指针的指向的的函数的两个参数是char和一个指向整形的指针,返回类型是void。
3.利用typedef简化复杂的声明
typedef void(* ret)(int)
//void(* func(char,void(*)(int)))(int)
ret func(char,ret);
2. int (*func[5])(int *);
typedef int (*p) (int *); p表示int (*)(int *)类型;
p func[5];
解读: func是含有五个元素的数组,每个元素是一个函数指针,这个函数指针指向的函数的参数是int*
返回类型是int
3. int (*(*func)[5])(int *);
typedef int (*p) (int *);
p表示 int (*)(int *)类型;
p(*func)[5]。
解读: func是一个指针,该指针指向一个五元素的数组,每个元素又是一个函数指针,这个指针所指类型是一个函数,该函数有一个整形指针参数并返回值是整型。
从上面的例子,我们可以看到通过typedef可以大大简化一些复杂的声明。
4.总结:
C/C++所有复杂的声明结构,都是由各种声明的嵌套构成的,理解复杂指针声明的时候,使用右左法则能够很有效帮助我们抽丝剥茧阅读指针。但是,我们要知道右左法则并不是C/C++标准规定的内容,它只是人们从C/C++标准的声明规定中提炼出来的方法。C/C++标准声明规则,是用来解决如何创建声明的,而右左法则是用来辨识一个声明的,从而帮助我们阅读代码。从嵌套的角度来看,彼此是一个相反的过程。