1.什么是复杂指针
int a;
int *a;
int * (*(*a));
int *(*(*pfun)(int *))[5];
(1)指向指针的指针
通常我们称int *a,指针a就是一个常见的指向int类型的指针变量。int **a就是一个二级指针,它是一个指向指针的指针,int *是一个整体,被指向对象。
而三级指针int ***a同样如此, 所指的对象是一个int **类型,所以可称其为一个一个指向指针的指针,他所指向的指针指向一个指向整型数的指针。
(2)指针,数组和函数的结合
当指针和数组与函数结合时,一个表达式可能会变得相当复杂。
我们以前领教过形如int *(*pfun)(int *)的函数指针的函数,也见识过int *(*pa)[5]的数组指针的数组。
(3)对于int *(*(*pfun)(int *))[5]
即便如此,我们看到int *(*(*pfun)(int *))[5]这种表达式也会感觉到很奇怪,他到底是数组还是指针或者时函数?
这个时候我们应该一步步的分解它,首先看到他的变量名pfun,它结合了一个*变成*pfun,所以无疑它是一个指针,(*pfun)的之外左边是*,右边是(int *)。
当遇到这种情况我们考虑运算符的结合和优先级,所以(*pfun)先结合(int *)形成(*pfun)(int *),这时pfun是一个指向函数的指针。
然后结合左边的*变成*(pfun)(int *),函数指针pfun返回了一个指针值。(*(*pfun)(int *))之外又面临和*还有[]结合的问题。
针对此类问题,如果没有运算符在()内,都是从右往左结合的,(*(pfun)(int *))先结合[5]形成(*(*pfun)(int *))[5]。
我们说函数*(*pfun)(int *)返回了一个指针值,所以(*(*pfun)(int *))结合了一个[5]也就是指向数组的指针,不过这个指针作为函数指针的返回值。
最后结合外层的*变成*(*(*pfun)(int *))[5]变成一个指针函数,所以这个表达式总体来看是一个int类型的复合指针函数。
我们给int *(*(*pfun)(int *))[5]命一个名为:一个指针所指向的函数的返回值类型的指针指向5个整型指针的数组。
2.更多复合指针的解析
(1)接下来看看类似的复合指针
int *(*fun[5])(int *);从内到外分别是指针数组,函数指针和指针函数。命名为五个指针类型的数组,每个指针指向一个返回值为整型指针的函数。
int (*(*fun)(int *))[5];从内到外分别是函数指针,指针函数和数组指针。
(2)对于int (*printSum(int a, int b, int (*pfun)(int,int)))(int,int)
我们再了解了这些指针的结合之后,对于上篇文章中出现的这个函数原型也可以解析一下。
从它函数名printSum开始,先结合(int a, int b, int (*pfun)(int,int))作为参数(两个int和一个int型函数指针),它是一个函数。
*printSum(int a, int b, int (*pfun)(int,int))到这个部分,它是一个指针函数,也就是返回值是指针。
int (*printSum(int a, int b, int (*pfun)(int,int)))(int,int)而该指针又和外部的int (int,int)结合形成int (*)(int,int)变成函数指针。
而此函数指针就是他的返回值。它是一个返回函数指针的函数。
这样就解释了printSum函数为什么不是int (*)(int,int) printSum(int a,int b, int (*pfun)(int,int))。
(3)复合指针的使用案例
一个经典的c语言复合指针案例(*(void(*)())0)();它是一个值强制转换为函数指针再进行函数调用。