引言:回調(diào)函數(shù)是 C 語言中函數(shù)指針
的一種用法,在一個函數(shù)A中通過函數(shù)指針調(diào)用另一個函數(shù)B的過程稱為回調(diào)(callback)
,通過函數(shù)指針被調(diào)用的函數(shù)B就是回調(diào)函數(shù)
?;卣{(diào)讓函數(shù) B 的代碼更加泛化和抽象,增強了程序的靈活性和可維護性。linux 底層驅(qū)動和 lwip 協(xié)議棧內(nèi)部都大量使用了回調(diào)函數(shù),回調(diào)函數(shù)實在是 編程人員不得不知的編程技巧。
在下述程序中函數(shù) test2_cal()
中調(diào)用函數(shù)指針 s_cal 指定的函數(shù)
執(zhí)行數(shù)值的計算。則s_cal 指定的那些函數(shù)
就可以看作一個回調(diào)函數(shù)。
typedef int (*my_calculate_t)(int a, int b);
static int cal_sum(int a, int b)
{printf("now is sum\r\n");
return a + b;
}
static int cal_sub(int a, int b)
{printf("now is sub\r\n");
return a - b;
}
static int cal_mul(int a, int b)
{printf("now is mul\r\n");
return a * b;
}
static my_calculate_t s_cal = cal_sum;
static int test2_cal (int a, int b)
{int result = 0;
if(s_cal) {result = s_cal(a ,b);
printf("result=%d\r\n", result);
}
return result;
}
void app_main(void)
{printf("init done\r\n");
int m = 10, n = 1, ret;
ret = test2_cal(m, n);
}
上述程序中 s_cal 的值為cal_sum()
,函數(shù) cal_sum()
就是一個回調(diào)函數(shù);即當前要執(zhí)行的運算為cal_sum
定義的加法運算。
當前程序的輸出結(jié)果:
init done
now is sum
result=11
也可以改變 s_cal 的值為cal_sub
,cal_mul
,它們分別對應(yīng)減法、乘法運算。讀者可自行賦值進行測試。
小結(jié):從上述測試,我們不難理解,僅僅通過更改一個s_cal
函數(shù)指針的值分別指向cal_sum
,cal_sub
,cal_mul
就可以實現(xiàn)整個程序運行不同的運算。運算的接口被統(tǒng)一為test2_cal()
,它具備了執(zhí)行多種運算的功能(通過更改s_cal
函數(shù)指針的值指定其功能)。另外,從該示例中,對于回調(diào)函數(shù),我們還認識到它往往具有一個外殼
,如本例中的test2_cal()
就是外殼,和一個核心
,即函數(shù)指針,如本例中的s_cal
函數(shù)指針。
回調(diào)對于編寫庫文件有很大的好處,比如我們要實現(xiàn)一個加法,但加法分很多種:整數(shù)的加法、字符串的加法、指針的加法等等。我們可以定義一個統(tǒng)一的add()
,并在add()
中定義一個函數(shù)指針s_add
,通過更改s_add
所指的函數(shù),來適應(yīng)多種數(shù)據(jù)類型的加法。這在C++ 中被稱為“多態(tài)”,即根據(jù)輸入的數(shù)據(jù)類型,調(diào)用符合該數(shù)據(jù)類型運算的函數(shù)。
同樣的,在編寫驅(qū)動程序時,由于不同的設(shè)備具備不同的特性,初始化時的內(nèi)容可能不一樣。使用回調(diào)函數(shù),可以通過改變對應(yīng)的函數(shù)指針的值,來指向不同的設(shè)備的初始化函數(shù),實現(xiàn)能夠兼容許多設(shè)備的驅(qū)動程序。
如上所示,回調(diào)函數(shù)是通過函數(shù)指針來調(diào)用的。因此想改變回調(diào)函數(shù)的功能,就是研究如何改變函數(shù)指針的值。主要有以下三種方法:
1)編譯時直接賦值如上一節(jié)所示的示例,通過對函數(shù)指針s_cal
賦值,可以改變函數(shù)test2_cal()
實際運行的計算。這在編譯時就知道要將函數(shù)指針s_cal
賦予的值的情況下,可以使用。若在編譯的時候不知道具體要將s_cal
賦予什么值,或者需要程序運行時動態(tài)地改變s_cal
的值,直接賦值的方法無法正常使用。
運行時,可以通過其他函數(shù)對函數(shù)指針進行賦值,在程序運行的時候,動態(tài)地改變函數(shù)的行為。
示例:
typedef int (*my_calculate_t)(int a, int b);
static int cal_sum(int a, int b)
{printf("now is sum\r\n");
return a + b;
}
static int cal_sub(int a, int b)
{printf("now is sub\r\n");
return a - b;
}
static int cal_mul(int a, int b)
{printf("now is mul\r\n");
return a * b;
}
static my_calculate_t s_cal = cal_sum;
static int test2_cal (int a, int b)
{int result = 0;
if(s_cal) {result = s_cal(a ,b);
printf("result=%d\r\n", result);
}
return result;
}
static void my_cal_calculate_register(my_calculate_t cal)
{s_cal = cal;
}
static void my_cal_calculate_unregister(void)
{s_cal = NULL;
}
void app_main(void)
{printf("init done\r\n");
int m = 10, n = 2, ret;
ret = test2_cal(m, n);
my_cal_calculate_register(cal_sub);
ret = test2_cal(m, n);
my_cal_calculate_unregister();
my_cal_calculate_register(cal_mul);
ret = test2_cal(m, n);
my_cal_calculate_unregister();
}
運行結(jié)果:
init done
now is sum
result=12
now is sub
result=8
now is mul
result=20
小結(jié):上述程序通過函數(shù)my_cal_calculate_register()
動態(tài)地改變函數(shù)指針s_cal
的值,從而實現(xiàn)在函數(shù)中動態(tài)地改變test2_cal
功能的目的。一些庫文件的源代碼是不開放的,因此,一些庫中使用這種通過動態(tài)注冊函數(shù)的方法來動態(tài)地指定庫函數(shù)實際功能。
typedef int (*my_calculate_t)(int a, int b);
static int cal_sum(int a, int b)
{printf("now is sum\r\n");
return a + b;
}
static int cal_sub(int a, int b)
{printf("now is sub\r\n");
return a - b;
}
static int cal_mul(int a, int b)
{printf("now is mul\r\n");
return a * b;
}
static int test1_cal (my_calculate_t actual_cal, int a, int b)
{int result = 0;
result = actual_cal(a ,b);
printf("result=%d\r\n", result);
return result;
}
void app_main(void)
{printf("init done\r\n");
int m = 10, n = 2, ret;
ret = test1_cal(cal_sum, m, n);
ret = test1_cal(cal_sub, m, n);
ret = test1_cal(cal_mul, m, n);
}
運行結(jié)果:
init done
now is sum
result=12
now is sub
result=8
now is mul
result=20
小結(jié):上面的示例在調(diào)用 test1_cal() 時,通過傳遞要運行的運算函數(shù),實現(xiàn)同一個函數(shù)test1_cal
執(zhí)行多個功能。同名函數(shù)傳遞不同參數(shù)執(zhí)行不同的功能,也是增強函數(shù)兼容性的常見方法。
本篇文章重點簡述了回調(diào)、回調(diào)函數(shù)的概念。本質(zhì)上,回調(diào)函數(shù)是 C 語言中函數(shù)指針
的一種用法。回調(diào)函數(shù)用于在統(tǒng)一的接口內(nèi),實現(xiàn)可以動態(tài)地改變函數(shù)的功能。
回調(diào)函數(shù)的實現(xiàn)至少需要兩個函數(shù),一個是外殼,一個是可以通過函數(shù)指針指定實際的被執(zhí)行的函數(shù)。
動態(tài)改變回調(diào)函數(shù)的實現(xiàn)的方法主要有三種:
1)編譯時直接賦值
2)運行時實現(xiàn)動態(tài)注冊
3)作為函數(shù)參數(shù)傳遞到指定的函數(shù)內(nèi)
下一節(jié):回調(diào)函數(shù)的典型使用場景
(碼字不易,謝謝點贊或收藏)
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁標題:詳解C語言中回調(diào)函數(shù)的含義與使用場景[1]-創(chuàng)新互聯(lián)
分享地址:http://jinyejixie.com/article24/dphhce.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、營銷型網(wǎng)站建設(shè)、響應(yīng)式網(wǎng)站、關(guān)鍵詞優(yōu)化、微信公眾號、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容