数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 1111|回复: 8

[STM] 实践理解 函数指针和回调函数

[复制链接]
发表于 2024-7-29 11:01:16 | 显示全部楼层 |阅读模式
本帖最后由 inthsunshine 于 2024-7-29 11:27 编辑

前阵子看一个解码器的资料,输入数据是以回调函数形式实现,之前也一直没留意没用过,得赶紧补缺补漏

自己写了简单的测试程序运行,更好理解它们

首先是函数指针的定义,和函数定义有点象
uint8_t (*func_pt)(uint8_t a);   //形参的参数名不写也可以编译通过,比如去掉a, (uint8_t)
另一种定义方法
typedef uint8_t (*func_pt1)(uint8_t);
func_pt1 func_pt;

所谓的函数指针,本质上就是一个指针变量,指向函数的变量, 和普通的指针变量类似
翻看编译后的map表,在内存占用4字节, 存储的是地址


为了使用函数指针,先定义2个简单函数,这2个函数的返回值和参数和前面的函数指针是完全一样
uint8_t callback1(uint8_t a) { return (a+1); }
uint8_t callback2(uint8_t a) { return (a-1); }

既然是函数指针,自然可以使用它,比如
  uint8_t tmp;
  func_pt=&callback1;    //给指针赋值
  tmp=(*func_pt)(6);    //调用callback1,也可写成func_pt(6)
  func_pt=callback2;      //也可以把取地址符号&去掉,同数组名类似,函数名也代表起始地址
  tmp=(*func_pt)(6);    //调用callback2

当然也可以定义函数指针数组
uint8_t (*callbackfunc[]) (uint8_t)={callback1,callback2};
再调用
func_pt=callbackfunc[1];
tmp=(*func_pt)(6);    //调用callback2

关键来了,函数可以成为另一个函数的入口参数,也就是函数可以当成参数传递。
比如以下函数,第2个参数是函数指针
uint8_t b(uint8_t c, uint8_t (*func)(uint8_t))    //或者uint8_t b(uint8_t c, func_pt1 func)
{  ....
   return (*func)(c); }

调用该函数
tmp=b(6,callback1);   //调用callback1
tmp=b(6,callback2);   //调用callback2
调用b函数时,需要提供另一个函数名作为参数,然后b运行后,会执行传递过来的函数,比如callback1,callback2,那么这2个函数称为回调函数

从编译后的汇编程序看,调用b函数时,第一个参数传给内部寄存器r0, 第二个参数传给r1,也就是callback1的地址
在b函数内部,传递过来的r1,最后成了跳转指令的目标地址,实现执行回调函数callback1


使用回调函数的好处是,假设b函数里面有一些是每次都要执行的固定操作,有些是根据情况执行可变的操作,那么,可以保持不修改b程序的情况下,通过传递不同的函数,来实现可变操作,这样的b函数通常是底层函数,可以和应用程序做分离。

不过话说回来,一个人就可完成的不大的diy程序,用到回调函数的必要性不大,或者说可以用if语句也能实现类似的功能,大概比较规范的代码,或者多人协作的大程序才需要吧。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x

打赏

参与人数 2家元 +90 收起 理由
慕名而来 + 30 謝謝分享
家睦 + 60

查看全部打赏

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-21 15:55 , Processed in 0.140400 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表