网站首页 > 技术文章 正文
提到回调函数,我也顺手在网上翻了一下,我发现说的都比较详细甚至于冗长了。很多人的解说都比较类似,回想当初自己刚接触的时候,我打算从一个非常简单的角度用几段话说完回调函数的使用和理解。
重点来了:什么是回调函数?
在程序中把你的函数换成函数指针,用指针去替代你本该写的函数名,这个被替代的函数就是回调函数。
结束!
用个简单的代码演示一下
//这里是它的头文件 Led.h
#ifndef __LED_H__
#define __LED_H__
void Led_On(void);
#endif
//这里是一个文件 Led.c
//这是一个函数,假设它有个功能,就是点亮LED灯
void Led_On(void)
{
LED = TRUE;
}
这里有另一个程序文件
//这里是它的头文件
#ifndef __SWITCH_H__
#define __SWITCH_H__
#include "Led.h" //方法一,引用LED头文件
void Get_Switch_State(void);
#endif
//这里是另一个文件 switch.c
//这里有另一个函数,假设它检测到某信号后需要点亮LED灯和处理一些事情;
extern void Led_On(void); //方法二,外部申明一下Led_On函数,如此才能跨函数调用
void Get_Switch_State(void)
{
if (Signel == TRUE)
Led_On(); //调用Led_On()函数,实现点亮LED功能
//.......
//do something
}
/* 要想能正常调用Led_On()函数,必须使用以上两个方法之一
*/
上面就是一个普通的程序流程,流程中有个普通的函数调用,如果,我将Get_Switch_State()中的Led_On()更换成指向Led_On()函数的函数指针,那么这时候Led_On就成了回调函数。
还是在另一个程序文件中
//这里是它的头文件
#ifndef __SWITCH_H__
#define __SWITCH_H__
#typedef void(*pFun)(void); //函数指针原型定义 重点一
void Get_Switch_State(void);
void CallBack_Reg(pFun cb);
#endif
//这里是另一个文件 switch.c
//这里有另一个函数,假设它检测到某信号后需要点亮LED灯和处理一些事情;
pFun CallBack_Ptr; //定义一个函数指针 重点二
//回调函数的注册函数CallBack_Reg()
void CallBack_Reg(pFun cb)
{
if (CallBack_Ptr == 0) //为函数指针赋值,当然它首先要没有被赋值
CallBack_Ptr = cb;
}
void Get_Switch_State(void)
{
if (Signel == TRUE)
CallBack_Ptr(); //调用Led_On()函数的指针,实现点亮LED功能 重点三
//.......
//do something
}
/* 发现关键点没有? switch.c 中再也没有出现Led_On();那它如何实现调用?
答案是还需要在其它地方
比如说main函数中把Led_On()函数和CallBack_Ptr 这个指针绑定一下
*/
void main(void)
{
Gpio_Init();
Bsp_Init();
Timer_Init();
CallBack_Reg(Led_On); //重点四
while (1)
{
.......
}
}
从上面的代码中可以明显发现几个特点
1.switch.c和.h中没有出现Led_On()函数了。 Led_On()函数被函数指针CallBack_Ptr替代了。
2.switch.c和.h中没有在引用文件Led.h了,实现了两个c文件的解耦,使他们的关联性降低了。
此时函数Led_On()就可以被称作 回调函数 了。
讲解完毕
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
好像还有点意犹未尽
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
总结一下,不要被回调函数的各种高深讲解给弄晕了头脑,它实际就是将你的函数用函数指针替代了,函数指针中存放的就是你的函数地址。
为了让函数指针CallBack_Ptr能指向你Led_On()的地址,你需要做一个注册功能函数CallBack_Reg(),将你要调用的函数地址传递给函数指针CallBack_Reg(Led_On);即CallBack_Ptr = Led_On。
这样,在调用CallBack_Ptr 的时候就等于调用了Led_On。
完美解决。。
最后说明一下函数指针的定义
typedef void(pFun *)(void); //第一个void表示指向的函数返回参数为空,第二个void表示输入参数为空
对比一下它要指向的函数 void Led_On(void) ; 数数void数量和位置理解了吧。
那如果有个函数带有输入参数怎么办呢?
聪明的你一定想到了
typedef void( pFun *)(unsigned char);
它可以指向的函数就如同 void Led_OnOff(unsigned char ) ;
使用
pFun CallBack_Ptr ; //定义函数指针
..........//注册函数指针
CallBack_Ptr (InputDat); //使用函数指针,并传递值InputDat给了函数
.........
对于有返回值和多个输入参数的函数就希望聪明的你举一反三了!
完毕!
猜你喜欢
- 2025-06-23 Qt qsort用法 完整版(解释了cmp)(qt中setshortcut的作用)
- 2025-06-23 学习笔记单片机的40个经典实验之5:报警产生器
- 2025-06-23 for、while、do while三种循环的流程图画法总结
- 2025-06-23 Proxy(代理)-对象结构型模式(js 代理对象)
- 2025-06-23 精品博文stm8自学笔记 2016/3/15(stm8系列选型表)
- 2025-06-23 【Linux系统编程】fork()函数详解
- 2025-06-23 链表 | 如何判断两个单链表(无环)是否交叉
- 2025-06-23 C语言灵魂:指针是什么及其常见用法
- 2025-06-23 51单片机-定时器(简易时钟的实现)
- 2025-06-23 基于时间触发任务调度软件架构(基于时间触发任务调度软件架构的设计)
- 最近发表
-
- Java中玩转JSON:让数据交互变得简单又有趣
- 爬虫逆向学习-下载网易云音乐(爬虫逆向分析)
- 一篇长文带你在Python里玩转Json数据
- 为何推荐 JsonTree.js 做 JSON 可视化?
- 能运行,不代表它是对的:5 个潜伏在正常功能下的 JavaScript 错误
- 让Android开发者轻松解析json数据的三种工具
- 必知必会!Python json模块全解析(python json encode)
- JavaScript的Symbol,解决了多少你不知道的隐形大麻烦?
- JSON 对象的这些操作和使用场景你知道多少?
- JSON 对象的克隆:浅拷贝与深拷贝(jsonobject深拷贝)
- 标签列表
-
- cmd/c (64)
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)