回调函数是老生常谈的事情,一名基本熟练C语言语法的编程者,在慢慢成为一定经验的编程者的过程中,想必都会经历熟练使用回调函数的阶段,这也是很多企业在面试时喜欢考察的技术题之一。
一、定义
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
举个例子,通俗一点讲是这个样子:
诸葛亮给赵子龙一个锦囊,吩咐他危急时打开按锦囊指示办,锦囊里的命令就是回调函数,危急时刻就是回调的时机。
还有一个例子:
设想你是某高大上企业老总,你要出国度假,临走前你只把一个私人电话号码(回调函数的地址)留给前台MM,告诉她,如果王思聪来找我(回调条件),你就给打这个电话Call(回调)我和他谈事情(回调函数)。
简而言之,回调函数是一个通过函数指针调用的函数。如果你把函数指针(函数的入口地址)传递给另一个函数,当这个函数指针被用来调用它所指向的函数时,我们就说这个函数是回调函数。对指针的应用是C语言编程的精髓所在,而回调函数就是C语言里面对函数指针的高级应用。
我们提到了函数指针,就拓展一下“函数指针”和“指针函数”。
函数指针:函数指针是指向函数的指针变量。因而“函数指针”本身首先应是指针变量,只不过该指针变量指向函数。这正如用指针变量可指向整型变量、字符型、数组一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是大体一致的。函数指针有两个用途:调用函数和做函数的参数。
指针函数:指针函数是指函数返回值带指针的函数,即本质是一个函数。函数都有返回类型(如果不返回值,则为无值型),只不过指针函数返回类型是某一类型的指针。
二、使用
(1)定义回调函数指针
既然说回调函数是一个通过函数指针调用的函数,那么这个函数指针该如何定义呢?我们经常会定义各种不同类型的指针,如
int *ptr; //整型指针 char *ptr; //字符型指针 struct my_struct *ptr; //结构体指针
同理,函数指针(指向函数的指针变量)一般定义方法为: 返回值类型 (*指针变量名)(函数参数列表)如
int (*ptr)(int, int); //int代表这个函数的返回值类型,ptr代表这个函数指针的名字,(int,int)代表传入函数的是两个int型参数
如果你要问函数指针为什么要这么定义,请先回答为什么整型指针的定义方式为 int *ptr 。
我们根据需要可以定义出各种所需的函数指针:
int (*ptr1)(void);//返回值类型为int,名字为ptr1,无形参的回调函数指针 void (*ptr2)(char* ,struct my_struct*, enum my_enum);//返回值类型为无类型,名字为ptr2,参数含有字符型指针、结构体指针、枚举类型的回调函数指针 ……
但是,注意了!我们通常不会以上述方式去定义函数指针,而是通过typedef关键字,为回调函数指针命名,使代码更具有可读性。
typedef int (*callBackFun)(char *); // 为回调函数指针命名,指针变量名为 callBackFun,参数为char *,等价于int (*ptr)(char *);
(2)定义回调函数
其实就是写一个普通的函数,里面含有当这个回调函数被调用时,要做的事情,如
(3)定义回调条件int func_callBack(char *my_string) { printf("%s\r\n", my_string); }
仍旧是写一个普通的函数,里面可以定义回调时机,或者说是回调条件(4)执行回调函数
int func(int handle_flag, char *date, callBackFun cb) { if(handle_flag == 1) cb(data); return 0; }
void main(void) { char data[256]="Learn how to use call back func"; func(1, data, func_callBack); }
运行结果:
欧了 ,搞定!
#include <string.h>
typedef int (*callBackFun)(char *);
int func_callBack(char *my_string)
{
printf("%s\r\n", my_string);
return 0;
}
int func(int handle_flag, char *data, callBackFun cb)
{
if(handle_flag == 1)
cb(data);
return 0;
}
void main(void)
{
char data[256]="Learn how to use call back func";
func(1, data, func_callBack);
}