在網上看了許多關於回調函數的解釋,感覺沒能get到主要的一個點,就自己寫一下對回調函數的理解及回調函數的應用場景和作用吧
1、官方定義
回調函數就是一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。
2、函數指針
理解回調函數前必須知道什么是函數指針
函數指針也是一種指針,只是它指向的不是整型,字符型而是函數。在C中,每個函數在編譯后都是存儲在內存中,並且每個函數都有一個入口地址,根據這個地址,我們便可以訪問並使用這個函數。函數指針就是通過指向這個函數的入口,從而調用這個函數。
int fun();
int (*p)();
fun是一個返回值為整型的函數
p是一個指針,指針指向一個函數,函數的返回值是整型
p = fun; 函數fun把地址賦給函數指針p
下次調用fun()可以直接用 (*p)( ) 或者 p( )
為什么可以直接用p(),因為函數名本質也是一個地址,函數指針本質也是一個地址,把地址fun賦給地址p ,p不就等於fun了嗎,(*p)和p相當於間接訪問和直接訪問的關系,不用糾結過多
3、回調函數
回調函數就是你寫一個函數,把函數地址賦值一個函數指針,然后把這個函數指針當作參數賦給另一個函數,另一個函數通過函數指針的地址調用這個函數,就是回調函數,他有什么作用呢,舉個例子
比如,我們寫A B C D 四個函數,封裝成一個庫文件,然后我們的主函數里面要寫一個功能函數,這個功能要用到函數A,假如不用函數指針,這個功能函數就要調用函數A,下次如果用到函數B,那么我們得刪掉A,調用函數B,每次都要修改這個函數很麻煩,但如果使用回調函數就不一樣了,我們可以定義4個函數指針,把4個函數的地址分別賦給4個函數指針,然后將函數指針當作參數傳遞給功能函數,功能函數就可以通過修改參數來調用對應的函數,而它本身不用做任何的修改。這樣的話,功能函數就可以根據不同的情況,通過函數指針去調用不同的函數,代碼如下
#include <stdio.h> #include <stdlib.h> float ADD(float a, float b) { return a + b; } float SUB(float a, float b) { return a - b; } float MUL(float a, float b) { return a * b; } float DIV(float a, float b) { return a / b; } float (*A)(float x, float y) = ADD; float (*B)(float x, float y) = SUB; float (*C)(float x, float y) = MUL; float (*D)(float x, float y) = DIV; float fun(float x, float y, float(*p)(float x, float y)) { return p(x, y); } int main() { printf("%f", fun(2, 3, A)); }
再舉一個例子,我們要實現一個函數,函數的功能是查找鏈表里面的某一個值,那么函數設計兩個參數,一個是鏈表第一個結點的指針,還有一個要查找的數,這時候問題就來了,鏈表的值可能是整型,也可能是字符,不同的類型對應的參數類型也不同,比較的方式也不同,這時候就需要用到回調函數,可以寫一個比較兩個值的函數,然后把函數地址賦值給一個函數指針,函數指針當作參數放到功能函數里作為第三個參數,功能函數就可以通過函數指針調用比較函數,並把兩個值傳給回調函數,比較函數獲取到兩個值后,通過強制類型轉換比較兩個值,返回結果。代碼如圖


希望可以通過這兩個例子幫助大家理解回調函數的使用,回調函數本質上就是函數指針的原理
轉載請注明出處、作者,謝謝
