理解函数指针和回调函数

嚴華  金牌会员 | 2023-4-20 01:24:10 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 954|帖子 954|积分 2862

理解

函数指针

指向函数的指针。比如:
理解函数指针的伪代码
  1. void (*p)(int type, char *data); // 定义一个函数指针p
  2. void func(int type, char *data); // 声明一个函数func
  3. p = func; // 将指针p指向函数func
  4. p(1,"test"); // 调用方式1
  5. (*p)(1,"test"); // 调用方式2
复制代码
回调函数和回调

比如,B把自己函数cbkFunc()的地址告诉A,A在运行过程中执行cbkFunc()。则
回调函数:指B的函数cbkFunc();
注册回调函数:指B把函数cbkFunc()的地址告诉A;
回调:指A在运行过程中执行cbkFunc()。
code


  • 无头文件.h
  • 为了方便模块A和B写在了一个.c文件中
  • 打印log的函数见参考博客[3],可以直接替换为printf()
FunctionPointTest.c
  1. /*
  2. * 理解函数指针和回调函数
  3. *
  4. * 假设需求:A要进行某项运动,有开始、正在做、结束3个状态,
  5. * B需要关注这3个状态
  6. *
  7. * 实现方案:A提供一个回调函数注册接口,在程序开始运行时,
  8. * B向A注册回调函数,A以回调函数的形式通知B
  9. *
  10. * 为了简便A和B写在一个文件里
  11. */
  12. #include "D:\MyFiles\MyLog\WindowsC\mylog.h"
  13. #include <stdio.h>
  14. #include <windows.h>
  15. // A和B的共同定义,一般是A的一个头文件,B会包含这个头文件:
  16. typedef enum ENUM_EVENT {
  17.         E_EVENT_START,
  18.         E_EVENT_DOING,
  19.         E_EVENT_FINISH,
  20. } EnumEvent;
  21. typedef void (*EVENT_CBK)(EnumEvent type, char *data);
  22. int regEventCbk(EVENT_CBK cbk);
  23. // A的实现
  24. #define TAGA "[MODULE_A]"
  25. static EVENT_CBK gSendEvent = NULL;
  26. int regEventCbk(EVENT_CBK cbk) {
  27.         if (cbk == NULL) {
  28.                 return -1;
  29.         }
  30.         gSendEvent = cbk;
  31.         LOGI("%s{有人注册了回调函数:%X, 地址:%p}", TAGA, *gSendEvent, gSendEvent);
  32.         return 0;
  33. }
  34. void doing() {
  35.         gSendEvent(E_EVENT_DOING, "进行中..."); // 调用方式1
  36.         Sleep(1000);
  37. }
  38. void runA() {
  39.         LOGI("%s{我是A}", TAGA);
  40.         if (gSendEvent == NULL) {
  41.                 LOGW("%s{B不关心我}", TAGA);
  42.                 return;
  43.         }
  44.         (*gSendEvent)(E_EVENT_START, "我开始了哟"); // 调用方式2
  45.         doing();
  46.         (*gSendEvent)(E_EVENT_FINISH, "我好了");
  47. }
  48. // B的实现
  49. #define TAGB "[MODULE_B]"
  50. long long int gAStart = 0;
  51. long long int gAFinish = 0;
  52. void eventStartHandler(char *data) {
  53.         gAStart = GetTickCount();
  54.         LOGI("%s{A:%s}{%lld}", TAGB, data, gAStart);
  55. }
  56. void eventDoingHandler(char *data) {
  57.         LOGI("%s{A:%s}", TAGB, data);
  58. }
  59. void eventFinishHandler(char *data) {
  60.         long long int aDurS = 0;
  61.         gAFinish = GetTickCount();
  62.         LOGI("%s{A:%s}{%lld}", TAGB, data, gAFinish);
  63.         aDurS = (gAFinish - gAStart)/1000;
  64.         LOGI("%s{A %llds}", TAGB, aDurS);
  65.         if (aDurS < 10) {
  66.                 LOGI("%s{A 真快}", TAGB);
  67.         }
  68. }
  69. void onEvent(EnumEvent type, char *data) {
  70.         switch (type) {
  71.                 case E_EVENT_START:
  72.                         eventStartHandler(data);
  73.                 break;
  74.                 case E_EVENT_DOING:
  75.                         eventDoingHandler(data);
  76.                 break;
  77.                 case E_EVENT_FINISH:
  78.                         eventFinishHandler(data);
  79.                 break;
  80.                 default:
  81.                 break;
  82.         }
  83. }
  84. void careA() {
  85.         LOGI("%s{我的回调函数地址:%p}", TAGB, onEvent);
  86.         regEventCbk(onEvent);
  87. }
  88. void runB() {
  89.         LOGI("%s{我是B}", TAGB);
  90.         careA();
  91. }
  92. int main() {
  93.         LOGI("{start}");
  94.         runB();
  95.         runA();
  96.         return 0;
  97. }
复制代码
运行结果


可优化点

.
参考博客

[1] https://zhuanlan.zhihu.com/p/162578969
[2] https://blog.csdn.net/zhou8201/article/details/100700479
[3] https://blog.csdn.net/qq_31300101/article/details/130190026?spm=1001.2014.3001.5502

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

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

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

嚴華

金牌会员
这个人很懒什么都没写!

标签云

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