回调函数 —— 借助中间通用函数(形参里有函数指针,实现函数注册)调用不同的回调函数 (多态/分层)
回調函數傳參:函數指針做函數參數(回調函數)
目錄
- 背景
- 回調函數是實現函數分層且單向依賴的好辦法,使用函數指針運行
- struct結構體回調函數代碼更清晰
- 簡單理解回調函數
- Demo
- 其他回調函數博文
背景
這是我在實際工作中遇到的問題:
線程創建 第三個參數 函數指針
完全不管具體實現什么功能,把地址傳過來,完全分層,黑盒子
涂鴉:那個接口有我解析的代碼,也有mcu調用者的代碼,耦合在一起了
要完全分層,雙方代碼要放在不同的 .c 文件里面,互不干擾。
回調函數是實現函數分層且單向依賴的好辦法,使用函數指針運行
回調函數是實現函數分層且單向依賴的好辦法,使用函數指針運行:
視頻講解【回調函數和函數指針】干貨分享,徹底擺脫回調地獄
實際工作中很常見的一種方法是,額外去寫一個注冊/安裝函數:
傳遞參數,底層給上層傳遞參數:
同時上層也可以給底層一個返回值,實現數據雙向的攜帶:
總結:
struct結構體回調函數代碼更清晰
參考:C/C++ struct 的回調函數使用技巧
地址:https://blog.csdn.net/u010333084/article/details/51339469?spm=1001.2014.3001.5502
回調函數是一個通過函數指針調用的函數。如果你把函數指針(函數的入口地址)傳遞給另一個函數,當這個函數指針被用來調用它所指向的函數時,我們就說這個函數是回調函數。可以作為函數參數傳遞哦。
使用struct 回調函數可以使得代碼更加清晰明了.
1.定義回調函數的原型
typedef int STRU_FU;STRU_FU sfun1(int a, const char *b){printf("fun1 a = %d , b = %s \n",a,b);return a; }STRU_FU sfun2(int a, void *b,float c){printf("fun2 a = %d , b = %f \n",a,c);return a; }STRU_FU sfun3(int a, char b,long c){printf("fun3 a = %d , *b = %ld \n",a,c);return a; }2. 定義的struct的回調函數
struct fun_ops{ //定義回調函數structSTRU_FU (*fun1)(int a, char *b); //注冊參數STRU_FU (*fun2)(int a, void *b,float c);STRU_FU (*fun3)(int a, char b,long c); };3. 注冊回調函數
struct fun_ops fuops = {//注冊初始化函數指針的函數.fun1 = sfun1,.fun2 = sfun2,.fun3 = sfun3, };4.完整的代碼
#include <stdio.h> #include <string.h> #include <pthread.h> #include <stdlib.h>typedef int STRU_FU;STRU_FU sfun1(int a, const char *b){printf("fun1 a = %d , b = %s \n",a,b);return a; }STRU_FU sfun2(int a, void *b,float c){printf("fun2 a = %d , b = %f \n",a,c);return a; }STRU_FU sfun3(int a, char b,long c){printf("fun3 a = %d , *b = %ld \n",a,c);return a; }struct fun_ops{ //定義回調函數structSTRU_FU (*fun1)(int a, char *b); //注冊參數STRU_FU (*fun2)(int a, void *b,float c);STRU_FU (*fun3)(int a, char b,long c); };struct fun_ops fuops = {//初始化函數指針的函數.fun1 = sfun1,.fun2 = sfun2,.fun3 = sfun3, };int main(int argc, char* argv[]) {int g;struct fun_ops *ops = NULL;if(argc < 2){printf("please input 1 or 2 or 3 for test fun \n");return -1;}if(strcmp(argv[1], "1") == 0){ops = &fuops;g =1;printf("fun1 \n");ops->fun1(111,"fun1");//調用回調}else if( !strcmp(argv[1], "2")){ops = &fuops;g= 2;printf("fun2 \n");ops->fun2(2222,"fun2",3333);}else{ops = &fuops;g = 3;printf("fun3 \n");ops->fun3(1212,'y',9999999);} }簡單理解回調函數
你到一個商店買東西,剛好你要的東西沒有貨,于是你在店員那里留下了你的電話,過了幾天店里有貨了,店員就打了你的電話,然后你接到電話后就到店里去取了貨。
在這個例子里,你的電話號碼就叫回調函數,你把電話留給店員就叫登記回調函數,店里后來有貨了叫做觸發回調事件,店員給你打電話叫做調用回調函數,你到店里去取貨叫做響應回調事件。
通過上面的例子我們有了以下幾點概念
-
主函數:相當于整個程序的引擎,調度各個函數按序執行
-
回調函數:一個獨立的功能函數
-
中間函數(通用):一個介于主函數和回調函數之間的函數,登記回調函數,通知主函數,起到一個橋梁的作用
在中間函數調用回調函數的時候,我們需要把回調函數當作參數來傳遞,那么就需要用到函數指針,下面以一個例子來詳細了解。
Demo
#include <stdio.h>//回調函數1 不同的調用者提供 類似多態 int callBack1(int x) {return x*2; } //回調函數2 不同的調用者提供 類似多態 int callBack2(int x) {return x/2; } //中間函數(通用) //函數指針 int calc(int b,int (* func)(int)) //func把函數當作參數來進行傳遞 {return 100+func(b); }int main() {int a=10;int q=calc(2,callBack1);//注冊:把函數賦值給函數指針的操作就是函數注冊printf("%d\n",q);int p=calc(4,callBack2);//注冊&調用回調函數printf("%d\n",p);return 0; }運行結果:
分析一下代碼流程
-
1、主函數需要調用回調函數
-
2、中間函數登記回調函數
-
3、觸發回調函數事件
-
4、調用回調函數
-
5、響應回調事件
其他回調函數博文
c語言回調函數的使用及實際作用詳解
C語言回調函數詳解(全網最全)
回調函數是什么,如何使用以及函數的注冊
C語言 | 嵌入式重點知識之回調函數
在函數中調用函數,有點象遞歸,遞歸調用的是自己。
總結
以上是生活随笔為你收集整理的回调函数 —— 借助中间通用函数(形参里有函数指针,实现函数注册)调用不同的回调函数 (多态/分层)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年亚太杯数学建模竞赛赛题
- 下一篇: ESP8266等模块