[C語言][筆記]回調函數(Callback Function) - 胖屁吉

文章推薦指數: 80 %
投票人數:10人

何謂Callback Function. 中文叫做回調函數,這應該算是C語言中比較進階的指標應用,這用法在Linux kernel裡面很 ... C語言Max程式筆記 [C語言][筆記]回調函數(CallbackFunction) byMax 2020-07-19 writtenbyMax 2020-07-19 何謂CallbackFunction 中文叫做回調函數,這應該算是C語言中比較進階的指標應用,這用法在Linuxkernel裡面很常見。

那麼Callback是一個什麼概念?(其實有點類似英文的Callmeback的意思)舉個簡單的例子,今天有位阿姨,她的技能是打掃,她遞了聯絡方式給我,然後跟我說,當你需要打掃的時候,Call我!,我就會來幫你打掃! boolaunt_do_clean(void){ //clean ... returntrue; } intmain(){ boolret; if(Ineedtoclean){ ret=aunt_do_clean(); } } 看到這邊,應該會有個疑問,這不就一般的函數範例?跟回調函數有什麼關係?以下舉個例子說明: 假如今天我蒐集了很多位阿姨的聯絡方式,有打掃阿姨,煮飯阿姨,倒垃圾阿姨,我用一隻手機來管理這些阿姨的連絡資訊,當今天我有不同需求的時候,全部都只要透過同一隻手機,我就可以呼叫不同阿姨來做事。

這段例子告訴我們一件事:使用同一隻手機==>可以呼叫不同功能的阿姨使用同一隻手機==>可以呼叫不同功能的API使用同一個callbackfunction==>可以呼叫不同功能的API 關於回調函數的理解部分,聽起來很玄,先貼個程式碼實際感受一下。

我自定義了一個Auntie的struct,並在裡面放了一個回調函數叫做self_introduce(),當程式在執行階段去執行此函數時,便可以觀察到,明明都是執行同一個函數,也沒帶任何參數,卻能跑出不同結果,這就是回調函數的實際體現。

typedefbool(*cb_func)(void); typedefstruct{ cb_funcself_introduce; }Auntie; intmain(){ inti; //自定義的結構體Auntie AuntiemWorkAuntie[3]; //初始化阿姨結構體的資料 mWorkAuntie[0].self_introduce=aunt_do_clean; mWorkAuntie[1].self_introduce=aunt_do_cook; mWorkAuntie[2].self_introduce=aunt_do_sleep; //叫每位阿姨來段自我介紹 for(i=0;i<3;i++){ mWorkAuntie[i].self_introduce(); } } 程式執行結果 實作回調函數前,要先認識幾個觀念 C的函數名稱其實代表指標,也就是函數指標,這個定義非常重要。

Example:aunt_do_clean/aunt_do_cook/aunt_do_sleep就是指標 //宣告一些函數 boolaunt_do_clean(void); boolaunt_do_cook(void); voidaunt_do_sleep(void); //對電腦來說,宣告的函數實作會放在記憶體上的某個區塊上,而name就代表該區塊的起始位置 bool0x112232(void);//將clean的實作放在以0x112232為起始位置的記憶體上 bool0x112252(void);//將cook的實作放在以0x112252為起始位置的記憶體上 void0x112278(void);//將sleep的實作放在以0x112278為起始位置的記憶體上 //當電腦要執行aunt_do_cook時 aunt_do_cook();//電腦會跳到0x112252的記憶體位置,開始跑函數實作部分 看到這邊是不是有啟發出什麼東西了 如果我們能把這些函數的的記憶體位置整理起來用個*pointer去代表,在程式執行階段,能夠動態的去將pointer換成想要執行的函數,那用起來是不是會更方便,能做更多技巧上的應用?沒錯!當有這個想法時,就代表已經有了回調函數的初步概念了 如何宣告函數指標? 首先,先來複習一下基本的指標example,在這個例子,可以很輕易地使用char*p來宣告成指標去做指向的動作 chararray[5]="Hi"; charword='c'; char*p; //讓p代表array p=array; //讓p指向word p=&word; 函數指標的宣告方式不太一樣,這邊介紹兩種宣告與用法 Type1:直接宣告一個回調函式的變數 boolaunt_do_clean(intlocation){ returntrueorfalse; } bool(*cb_func)(int)=NULL; intmain(){ intret; cb_func=aunt_do_clean; ret=cb_func(1); } Type2定義成一個回調函數的類型 boolaunt_do_clean(intlocation){ returntrueorfalse; } typedefbool(*cb_func)(int); cb_funcp_my_cb=NULL; intmain(){ intret; p_my_cb=aunt_do_clean; ret=p_my_cb(1); } 也可以在函數中直接傳入要宣告的指標函數 boolaunt_do_clean(intlocation){ returntrueorfalse; } voidfunc1(intlocation,bool(*convert_func)(int)){ ret=convert_func(location); } intmain(){ func1(1,aunt_do_clean); } 回調函數的完整程式碼 #include #include typedefbool(*cb_func)(void); typedefstruct{ cb_funcself_introduce; }Auntie; boolaunt_do_clean(void){ printf("Myjobiscleaning.\n"); returntrue; } boolaunt_do_cook(void){ printf("Myjobiscooking.\n"); returntrue; } boolaunt_do_sleep(void){ printf("Myjobissleeping.\n"); returntrue; } voidwork_dispatch(Auntie*list){ list[0].self_introduce=aunt_do_clean; list[1].self_introduce=aunt_do_cook; list[2].self_introduce=aunt_do_sleep; } intmain() { inti; AuntiemWorkAuntie[3]; work_dispatch(mWorkAuntie); for(i=0;i<3;i++){ mWorkAuntie[i].self_introduce(); } system("pause"); } 程式執行結果 Sharethis:TwitterFacebook 0comment 1 FacebookTwitterPinterestEmail Max Hi nextpost [android][筆記]透過addr2line,找程式哪一行發生crash Youmayalsolike [android... 2021-05-14 [android... 2021-05-14 關於我們 RecordOurLife 胖屁手札 彙整 2021年5月 2020年7月 分類 作者 Max Android 程式筆記 C語言 最新文章 [android][筆記]如何在android的裝置上執行自己寫的Cbinary [android][筆記]透過addr2line,找程式哪一行發生crash [C語言][筆記]回調函數(CallbackFunction) 作者近況Max[android][筆記]如何在android的裝置上執行自己寫的Cbinary[android][筆記]透過addr2line,找程式哪一行發生crash[C語言][筆記]回調函數(CallbackFunction) 熱門文章 [C語言][筆記]回調函數(CallbackFunction) 2020-07-19 [android][筆記]透過addr2line,找程式哪一行發生crash 2021-05-14 [android][筆記]如何在android的裝置上執行自己寫的Cbinary 2021-05-14 部落格統計2,904個點閱數



請為這篇文章評分?