本文介绍函数指针及其与回调函数联系。函数指针除了能够部分替代 C++ 中的函数模板,其更大的用处应该在于回调操作。
函数指针
函数指针是指向函数调用地址的指针。
它和函数名究竟有什么关系呢?且看下文。
且看一小程序
先请看下边程序:
1 |
|
程序的运行结果如下:
从上边程序,我们可以得到下边结论:
函数指针和函数名本质上是一样的,都是指向函数调用地址的指针,只是函数名是指针常量,函数指针是变量。
调用函数的写法 func()、(*func)() 均可,而我们大多数情况下都会写成前者,应该是(C/C++标准制定者)为了方便大家对函数的调用。
博文 Function Pointers and Callbacks in C — An Odyssey 如此说:
A pointer is a special kind of variable that holds the address of another variable. The same concept applies to function pointers, except that instead of pointing to variables, they point to functions. If you declare an array, say, int a[10]; then the array name a will in most contexts (in an expression or passed as a function parameter) “decay” to a non-modifiable pointer to its first element (even though pointers and arrays are not equivalent while declaring/defining them, or when used as operands of the sizeof operator). In the same way,
for int func();, func decays to a non-modifiable pointer to a function. You can think of func as a const pointer for the time being.
void (*pFunc)()与void* pFunc()区别
对于前者,我们都知道 pFunc 是函数指针变量
,函数的返回值是空(void)。
对于后者而言,情况却很不一样。pFunc 是函数指针常量
,函数的返回值是 void 指针。
*typedef void (pFunc)()是什么意思?
发现自己看不懂这个语句了!!!(*pFunc)() 是 void 的别名?这说不通啊!
typedef的语法如下:
1 | typedef type_declaration; |
为什么自己会看不懂,是因为自己一直把type_declaration
分成两个部分,后半部分是前半部分的别名。其实这是错的!!!type_declaration
一直是一个整体,而不是分成两半!还得注意,typedef 跟 #define 根本是两回事!
在下边的语句中,‘void (*pFunc)()’是完整的一个类型声明,也就意味着 pFunc 不再是一个函数指针变量,而是一个函数指针类型。
1 | typedef void (*pFunc)() |
下边是一个能够说明 typedef 的简单例子:
1 | // simple typedef |
有了函数指针类型,以后我们就可以像变量一样声明函数指针,如下例:
1 |
|
回调函数
回调函数其实就是一个通过函数指针调用的函数!
假如你把 A 函数的指针当作参数传给 B 函数,然后在 B 函数中通过 A 函数传进来的这个指针调用 A 函数,那么这就是回调机制。A 函数就是回调函数,而通常情况下,A 函数是系统在符合你设定条件的情况下会自动执行
。
例如Linux下的多线程创建函数:
1 |
|
中的start_rtn
就是一个回调函数。
下边是一个简易的例子:
1 |
|
通过这个小程序可以看出,相对于普通函数调用来说,回调函数至少有如下优势:
把回调函数定义成一个类型并作为调用函数的参数类型,这样只要跟该回调函数类型有相同声明而有不同实现的函数都可以被调用函数调用。这样将极大扩展调用函数的功能。
例如,我们可以定义N多个myFunc,而且互相之间实现各不相同,那对于callMyFunc来说就有N种功能。
关于回调函数详细可参考知乎上问答回调函数(callback)是什么?。