0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言函数的回调函数

工程师 来源:嵌入式客栈 作者:嵌入式客栈 2020-09-11 09:57 次阅读

来源:嵌入式客栈

1 什么是回调函数?首先什么是“回调”呢?

我的理解是:把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被调用执行,这就叫做回调。

如果代码立即被执行就称为同步回调,如果过后再执行,则称之为异步回调。

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

2 为什么要用回调函数?因为可以把调用者与被调用者分开,所以调用者不关心谁是被调用者。它只需知道存在一个具有特定原型和限制条件的被调用函数。

简而言之,回调函数就是允许用户把需要调用的方法的指针作为参数传递给一个函数,以便该函数在处理相似事件的时候可以灵活的使用不同的方法。

int Callback() ///《 回调函数{ // TODO return 0;}int main() ///《 主函数{ // TODO Library(Callback); ///《 库函数通过函数指针进行回调 // TODO return 0;}

回调似乎只是函数间的调用,和普通函数调用没啥区别。

但仔细看,可以发现两者之间的一个关键的不同:在回调中,主程序把回调函数像参数一样传入库函数。

这样一来,只要我们改变传进库函数的参数,就可以实现不同的功能,这样有没有觉得很灵活?并且当库函数很复杂或者不可见的时候利用回调函数就显得十分优秀。

3 怎么使用回调函数?int Callback_1(int a) ///《 回调函数1{ printf(“Hello, this is Callback_1: a = %d ”, a); return 0;}int Callback_2(int b) ///《 回调函数2{ printf(“Hello, this is Callback_2: b = %d ”, b); return 0;}int Callback_3(int c) ///《 回调函数3{ printf(“Hello, this is Callback_3: c = %d ”, c); return 0;}int Handle(int x, int (*Callback)(int)) ///《 注意这里用到的函数指针定义{ Callback(x);}int main(){ Handle(4, Callback_1); Handle(5, Callback_2); Handle(6, Callback_3); return 0;}

如上述代码:可以看到,Handle()函数里面的参数是一个指针,在main()函数里调用Handle()函数的时候,给它传入了函数Callback_1()/Callback_2()/Callback_3()的函数名,这时候的函数名就是对应函数的指针,也就是说,回调函数其实就是函数指针的一种用法。

4 回调函数实例(很有用)一个GPRS模块联网的小项目,使用过的同学大概知道2G、4G、NB等模块要想实现无线联网功能都需要经历模块上电初始化、注册网络、查询网络信息质量、连接服务器等步骤,这里的的例子就是,利用一个状态机函数(根据不同状态依次调用不同实现方法的函数),通过回调函数的方式依次调用不同的函数,实现模块联网功能,如下:

/********* 工作状态处理 *********/typedef struct{ uint8_t mStatus; uint8_t (* Funtion)(void); //函数指针的形式} M26_WorkStatus_TypeDef; //M26的工作状态集合调用函数/************************************************ 》M26工作状态集合函数***********************************************/M26_WorkStatus_TypeDef M26_WorkStatus_Tab[] ={ {GPRS_NETWORK_CLOSE, M26_PWRKEY_Off }, //模块关机 {GPRS_NETWORK_OPEN, M26_PWRKEY_On }, //模块开机 {GPRS_NETWORK_Start, M26_Work_Init }, //管脚初始化 {GPRS_NETWORK_CONF, M26_NET_Config }, /AT指令配置 {GPRS_NETWORK_LINK_CTC, M26_LINK_CTC }, //连接调度中心 {GPRS_NETWORK_WAIT_CTC, M26_WAIT_CTC }, //等待调度中心回复 {GPRS_NETWORK_LINK_FEM, M26_LINK_FEM }, //连接前置机 {GPRS_NETWORK_WAIT_FEM, M26_WAIT_FEM }, //等待前置机回复 {GPRS_NETWORK_COMM, M26_COMM }, //正常工作 {GPRS_NETWORK_WAIT_Sig, M26_WAIT_Sig }, //等待信号回复 {GPRS_NETWORK_GetSignal, M26_GetSignal }, //获取信号值 {GPRS_NETWORK_RESTART, M26_RESET }, //模块重启}/************************************************ 》M26模块工作状态机,依次调用里面的12个函数 ***********************************************/uint8_t M26_WorkStatus_Call(uint8_t Start){ uint8_t i = 0; for(i = 0; i 《 12; i++) { if(Start == M26_WorkStatus_Tab[i].mStatus) { return M26_WorkStatus_Tab[i].Funtion(); } } return 0;}

所以,如果有人想做个NB模块联网项目,可以copy上面的框架,只需要修改回调函数内部的具体实现,或者增加、减少回调函数,就可以很简洁快速的实现模块联网。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136615
  • 函数
    +关注

    关注

    3

    文章

    4326

    浏览量

    62555
收藏 人收藏

    评论

    相关推荐

    同样是函数,在CC++中有什么区别

    同样是函数,在 CC++ 中有什么区别? 第一个返回值。 C语言函数可以不写返回值类型,
    的头像 发表于 11-29 10:25 250次阅读

    使用C语言实现函数模板

      用C语言能不能实现一个通用的函数,既能完成整数的相加,又能完成浮点数的相加?
    的头像 发表于 11-09 11:38 364次阅读

    定时器函数能不能用ICACHE_FLASH_ATTR定义?

    非 OS SDK 在中断处理函数中,请勿使用任何 ICACHE_FLASH_ATTR 定义的函数。 请问: 1、定时器和hw定时器的函数
    发表于 07-22 06:33

    esp8266怎么找到函数被调用的地方?

    esp8266里的程序怎么运行? 在user_init里注册了espconn_regist_sentcb,espconn_regist_recvcb这几个函数,怎么找到这几个
    发表于 07-10 08:24

    在HTTP的demo里面,函数不执行的原因?

    在HTTP的demo里面,我用下面这个函数注册了一个函数,但是发现有时候正常执行有时候不执行,只是偶尔不执行,大部分时间是正常的。有没有人能提供一下原因可能的方向,谢谢!! es
    发表于 07-10 08:23

    请问ESP32C3 I2S驱动支持函数获取数据吗?

    目前I2S驱动只看到i2s_read接口获取数据,但这是polling方式的。是否有注册函数,当数据到达是调用回头函数通知上层app?
    发表于 06-28 06:11

    为什么无法停止使用cy_wcm_connect 的rtos定时器函数

    。 由于 cy_wcm_connect() 函数的某些原因,计时器无法停止。 取而代之的是调用回函数,由于设备已连接到 Wifi,它将再次尝试停止计时器。 我想知道如何以正确的方式停止计时器。 我测试了使用和不使用 cy_wc
    发表于 05-24 06:34

    stm32中断函数改变的变量在while中不变怎么解决?

    关于stm32 中断函数改变的变量在while中不变问题
    发表于 04-26 07:44

    stm32cubemx生成rtos后中断处理后执行的函数是否也有优先级?

    如题:函数是否也有优先级,我发现我的函数不能按照预想的来运行.
    发表于 04-25 08:16

    请问ucos-III中断保护放在中断函数还是中断里面?

    请教下ucos-III 中断保护放在中断函数还是中断里面? 1. 中断函数 void DMA2_Stream6_IRQHandler(void) { OS_ERRerr
    发表于 04-23 07:44

    函数(callback)是什么?函数的实现方法

    函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。
    发表于 03-12 11:46 2876次阅读

    浅谈C语言中的函数定义

    如果函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。 形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数
    发表于 03-11 10:09 375次阅读

    函数指针与函数的应用实例

    通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数函数指针可以像一般函数一样,用于调用函数、传递参数。
    的头像 发表于 03-07 11:13 398次阅读
    <b class='flag-5'>函数</b>指针与<b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>的应用实例

    ​​嵌入式中函数的实现方法

    函数的命名规范没有固定的标准,但是根据通用惯例和编码规范,函数的命名应该能够反映
    发表于 03-04 14:49 707次阅读

    如何给C语言中的函数定义两个不同的名字?

    最近有位哥问我,如何给C语言中的函数定义两个不同的名字?就是这两个名字都是指向同一个函数,同一个地址,而且两个名字都可以当做函数来用的那种。
    的头像 发表于 12-19 16:21 813次阅读