函数指针 && 返回函数指针的函数的一些姿势

函数指针一些知识
(1) ,  在mj下拉刷新中遇到了定义的一个宏,看起来比较晦涩,如下
#define msgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__)
其实就是把objc_msgSend函数指针强制转换成另一种类型((void (*)(void *, SEL, UIView *)))的函数指针,
所以这个宏表示的就是一个个函数指针
(void (*)(void *, SEL, UIView *))这一坨其实表示的是一个函数指针(指向一个函数的指针,这个函数返回值为void,有3个参
数),前面这一坨的意思就是把objc_msgSend这个函数指针转换成这一坨的指针类型。这样的好处就是可以限制这个宏接受的3个参数必须是这一坨中的3个参数。
调用的时候,可以这么调用:
objc_msgSend(ivar1,ivar2,ivar3);
这与(*objc_msgSend)(ivar1,ivar2,ivar3);是等价的。
下面分析为什么他们是等价的?
void (*funcPtr)(); // 这是一个函数指针
void *funcPtr();  //  这是一个函数
主要取决于运算符的优先级, funcPtr是应该先与坐边的*结合还是与右边的()结合, 因为函数运算符() 的优先级要高于单目运算符*,所以如 果没有括号那就先与()结合,那么它就是一个函数。

在《C陷阱与缺陷》中有这样一段描述:

fp是一个函数指针,那么*fp就是该指针所指向的函数,所以(*fp)()就是调用该函数的方式。ANSI C标准允许程序员将上式简写为fp(),但是一定要记住这种写法只是一种简写形式。

在表达式void (*func)()中,*func两侧的括号非常重要,因为函数运算符()的优先级要高于单目运算符*。如果*func没有括号,那么*func实际上与*(func())的含义完全一致,ANSI C把它写作*(*(fp)())的简写形式。

根据以上的描述,我们似乎可以得到这样一个结论:

       1. func是一个函数指针

       2. func()(*func)()的一个简写形式

       3. &func&(*func)的简写形式

如果这样理解正确的话,那么上面那段代码就顺理成章了。用宏定义了一个函数指针,然后使用的时候展开宏,就是调用一个函数指针,也就等同于调用这个函数objc_msgSend,因为objc_msgSend(...) 是等同于(*objc_msgSend)(...)的。

下面是一个面试题:
void * (*(*fp1)( int))[ 10];  // 表示的什么?

我们从里向外一点一点分析,首先(*fp1)(int),这说明fp1是一个函数指针,它有一个int类型的参数;然后我们来找这个函数指针类型的返回值,注意到*(*fp1)(int),所以我们可以断定它的返回值是一个指针,指针指向什么呢?

我们可以看到最外层剩余的部分是void* [10],因此这个函数的返回值是一个指针,这个指针指向一个包含十个void*类型数据的数组。

综上:fp1 是一个函数指针,它所指向的函数有一个int 类型的参数,并且这个函数的返回值是一个指针,这个指针指向一个包含10 void* 元素的数组。
总结最重要的一点:
        (*fp1)( int) 说明它是一个函数指针,这个好理解,然后再与左边*结合 * (*fp1)(int),说明它的返回值是一个指针,就如同:
int *func()说明这个函数指针的返回值是一个指针,指针的类型为int。
这个如果理解就好办了, 说明返回值是一个指针,那这个指针的类型是什么呢?就是void *[10],一个包含10个空指针的数组。
如果变一下,
int* (*fp2)( int)[ 10];  // 表示的什么?
首先,fp2是一个函数指针,很好理解,然后是先与左边的*结合还是与右边的[10]结合呢?根据运算符优先级,[]高于*,因此
函数的返回值是一个数组:int *[10], 而不一个指针。在C语言里面,数组是不能直接作返回值的,作为返回值的时候,必须转换成指针的,因此,这个语句会报错:
error: Function cannot return array type " int *[10] "

如果再变一下,加一个括号,
int(* (*fp3)( int))[ 10];  // 表示的什么?
首先,fp2是一个函数指针,很好理解,因为加了一个括号,所以函数的返回值是一个指针,那这个指针指向什么呢?
指向int[10](包含10个整型数据的数组)。这样就没有问题的,因为函数的返回值是一个指针,指向一个数组。

/*------------------------------------------------------------------------- * /
void  (*funcPtr)();  //  这是一个函数指针,因为 (*funcPtr) 优先结合,表示这是一个指针
void  *funcPtr();    //  这是一个指针函数 因为函数括号 () 优先级高于 * ,所以这是一个函数
int   *a[ 10 ];        //  这是一个指针数组,因为 []  优先级高于 * ,所以这是一个数组
int   (*a)[ 10 ];      //  这是一只数组指针 因为 () 优先级高级 [] ,所以这是一个指针
/*------------------------------------------------------------------------- * /

更具体的函数指针: http://blog.csdn.net/itianyi/article/details/42456753


(2),  在新行情重构中,遇到了调用的一个函数signal(信号量),也比较晦涩,如下:
void (*signal( int void  (*)( int )))( int );
这是一个返回函数指针的函数。
首先, signal按优先级先与函数()符号结合,那么它就是一个函数,
然后,再与左侧的*结合,表示返回值是一个void(*)(int)类型。如果按下面这么写就容易理解了:
typedef void(*PF)(int);
PF signal(int, void (*)(int))
更详细的返回函数指针的函数: http://blog.csdn.net/itianyi/article/details/42455953

你可能感兴趣的:(函数指针 && 返回函数指针的函数的一些姿势)