我们先来看一下函数的定义式:
<数据类型><函数名>(参数说明列表)
{
表达式;
}
回调函数与普通函数没什么大的差别,<数据类型>和<函数名>与一般函数定义相同。只是(参数说明列表)中的某个参数是一个函数指针。
--------------------------------------------------------------------------
例一:
这是一个很简单的代码
callback_1函数作用是打印“Hello”;
Handle函数的作用是打印“Hi”;
主函数(main函数)中,我们只需要调用函数Handle,并且给Handle函数一个参数(这个参数为callback_1,也就是第一个函数的函数名(地址))。这样就可以通过Handle函数调用callback_1函数。
所以运行结果:
我们可以看到,我们为了调用函数callback_1,也调用了函数Handle。“callback_1”被作为参数调用且执行。所以这个代码中,callback_1为回调函数,而Handle我们可以称为中间函数。
---------------------------------------------------------------------------------------------------------------------------
肯定有很多和我一样的小白有疑问:为什么我们想调用callback_1函数,不直接在主函数(main函数)中调用,反而要多此一举调用一次Handle函数?
要回答这个问题,我就举个生活中的例子:
假如,你进了一个饭店,老板要给你做饭(做饭的“做”这个动作就是中间函数),店里有很多菜,有鱼香肉丝,红烧茄子,土豆丝,番茄鸡蛋,想吃啥有啥。那么,你想吃番茄鸡蛋就要告诉老板:“老板来一份番茄鸡蛋。”当你告诉老板要吃啥,其实就是传参数,你告诉老板要吃番茄鸡蛋,“番茄鸡蛋”这个函数名(函数地址)。而你选择吃啥,吃番茄鸡蛋还是吃土豆丝,这个“选择”,就是在选择调用的函数。
用代码举例:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int callback_1()
{
printf("打篮球\n");
}
int callback_2()
{
printf("看电影\n");
}
int callback_3()
{
printf("约会\n");
}
int Handle(int (*callback)())
{
printf("我今天要");
callback();
}
int main(int argc, char *argv[])
{
Handle(callback_1);
Handle(callback_2);
Handle(callback_3);
return 0;
}
------------------------------------------------------
callback_1,callback_2,callbak_3,都为回调函数。Handle为中间函数,我们用主函数给中间函数传参,运行结果为:
回到问题上:为什么不直接调用想用的函数,而是通过中间函数呢。
由这个代码的运行结果来看,我们可以抽象的认为,回调函数与中间函数都拿来单独看,他们其实都不是完整的。如果把回调函数与中间函数看为一个整体,才是我们想要的结果(我今天要约会...)。
我们可以在主函数加上一个if(如果),如果今天气温低于30°,那么调用callback_1,我要去打篮球,如果今天有新电影上映了,那么调用回调函数_2,我今天要去看电影。
所以回调函数一般是用来————以便该函数在处理相似事件的时候可以灵活的使用不同的方法。
----------------------------------------------------------------------------------------------
在嵌入式中,我们可以看见很多回调函数:
(1)信号注册函数(通过命名的方式)
typedef void(*sighandler_t)(int);
Sighandler_t signal(int signum,sighandler_t handler);
(2)线程创建函数(直接通过函数指针)
#include <pthread.h>
Int pthread_create(pthread_t*thread,const pthread_attr_t*attr,void*(*start_routine)(void*),void*arg);
所以只要是通过函数名调用的函数,都可称为回调函数。
// 这就是我一个小白理解“回调函数”的一些看法。//