函数指针
c语言中的指针可以指向整数、字符或者结构体类型等,同样也可以指向一个函数,这就是函数的指针。函数指针的值等于该函数存放其二进制执行代码的内存区域的首地址(函数名代表函数代码的首地址)
函数指针
- 函数指针的声明
声明一个函数指针,例如
int (*p) (int,int);
上面声明了一个指针变量p,其指向的内容是一个函数,这个函数的返回值是int类型的,参数也是两个int类型的。声明了一个函数指针后就可以对其进行赋值。
- 函数指针的赋值
函数名的本质就是存放函数代码的内存空间的首地址,因此可以将一个函数名赋值给一个指向函数的指针,之后这个函数指针就可以表示这个函数了,如下
p = f; //f是函数名
- 函数指针的使用
引用一个函数指针相当于调用这个函数,如下
(*p)(1,2);
等价于f(1,2);
函数指针的应用——回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。也就是说,把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。如果代码立即被执行就称为同步回调,如果在之后晚点的某个时间再执行,则称之为异步回调。
-
为什么要用回调函数
因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。
简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
image.png
int Callback() ///< 回调函数
{
// TODO
return 0;
}
int main() ///< 主函数
{
// TODO
Library(Callback); ///< 库函数通过函数指针进行回调
// TODO
return 0;
}
回调似乎只是函数间的调用,和普通函数调用没啥区别。
但仔细看,可以发现两者之间的一个关键的不同:在回调中,主程序把回调函数像参数一样传入库函数。
这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,这样有没有觉得很灵活?并且当库函数很复杂或者不可见的时候利用回调函数就显得十分优秀。
How to use
小例子
main.c
#include <stdio.h>
#include "funcp.h"
int add(int,int);
int mul(int,int);
int main(int argc, char const *argv[])
{
int (*padd)(int,int) = NULL;
padd = add;
printf("%d\n",lib_function_calc(3,5,padd));
int (*pmul)(int,int) = NULL;
pmul = mul;
printf("%d\n",lib_function_calc(8,9,pmul));
return 0;
}
int add(int a,int b){
return a+b;
}
int mul(int a,int b){
return a-b;
}
funcp.h
#include <stdio.h>
int lib_function_calc(int,int,int (*func)(int,int));
funcp.c
#include "funcp.h"
int lib_function_calc(int a, int b,int (*func)(int,int)){
return (*func)(a,b);
}
可以看到我在我的main函数调用我的库函数,库函数的一个参数是函数指针,我们就把我们自己写的功能通过函数指针传递进去,实现我们的功能定制化......