1、定義數組
什麼是回調函數?它首先是一個函數,這是確定的,我舉個例子:有兩個函數A和B,首先應用程序將A的地址告訴B,這稱之爲註冊回調函數,B在收到外部某個命令的時候,能夠根據B的地址來調用A,這個先被傳入B,後面又被B調用的函數A就稱之爲回調函數。函數
這樣看來,判斷一個函數是否是回調函數是從它被調用的方式來定義的,那麼B函數通常來講須要一個傳入參數,參數類型是函數指針。spa
2、應用場景指針
有人可能會說,B想調用A直接在函數裏面直接調用就行了,爲何先要把A的地址做爲一個參數傳給B這麼麻煩呢?code
咱們能夠設想這樣一個生活場景:blog
商場裏有一款商品賣的特別好,常常賣斷貨,許多客戶都要求新貨一到就立刻聯繫他們,爲了商場能聯繫上客戶,客戶們就把本身的聯繫方式告訴商場(註冊回調函數),客戶A把本身的手機號告訴了商場,客戶B呢把本身的郵箱告訴了商場。等到新貨到了,商場就打電話(調用回調函數)通知客戶A,而通知客戶B則經過發郵件(調用回調函數)。接口
這裏咱們能夠看到,客戶把本身的聯繫方式告訴商場,至因而什麼聯繫方式商場並不關心,只要能聯繫上客戶就行,這樣就給客戶很大的靈活性。事件
再看一個具體的應用場景:回調函數
一個管理USB接口的模塊,這個模塊會不停的檢測USB接口是否有U盤插入。而當有U盤插入的這個事件發生時,不一樣的用戶可能想幹不一樣的事,好比有的用戶想在屏幕上顯示「有U盤插入了」,而有的用戶就想讓一個喇叭不停的響等等。那麼這個時候用戶只要把U盤插入響應函數的地址告訴模塊(註冊回調函數),等到模塊檢測到有U盤插入就去調用這個響應函數(調用回調函數),至於這個函數作些什麼,模塊並不關心,這就增長了用戶的靈活性,實現用戶想要的功能。event
3、怎麼用
從上面咱們看到須要把回調函數的地址做爲一個參數註冊到模塊中,這個函數地址其實就是個函數指針,既然要註冊到模塊中,這個回調函數必須以該模塊承認的格式編寫,說的比較抽象,下面舉個例子說明下。
先寫模塊部分,構造一個結構體
1 typedef struct _CheckEvent() 2 { 3 int eventID; 4 BOOL (*Check)(void); 5 }CheckEvent;
上面的結構體中定義了一個函數指針Check,參數是void,函數類型是BOOL,這就要求用戶定義的回調函數也必須是參數爲void、類型爲BOOL的函數。
接着定義一個CheckEvent的數組:
1 CheckEvent arrayCheckEvent[2]= 2 { 3 {0, CheckEvent0},//註冊回調函數CheckEvent0 4 {1, CheckEvent1}//註冊回調函數CheckEvent1 };
編寫模塊主功能:
1 void Module(void) 2 {
int index,id; 3 while(1) 4 { 5 id=GetEventID();
7 for(index=0;index<2;index++) 8 { 9 if(id == arrayCheckEvent[index]. eventID)//當事件eventID發生時 10 arrayCheckEvent[index]. Check();//調用eventID對應的回調函數 11 } 12 } 13 }
應用程序要作的就是實現回調函數
BOOL CheckEvent0(void)和BOOL CheckEvent1(void)了,實現用戶想要的功能,注意回調函數的參數和函數類型要和模塊中定義的CheckEvent結構體中的函數指針定義的一致。