歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C語言函數指針與回調函數

C語言函數指針與回調函數

日期:2017/3/1 9:27:01   编辑:Linux編程

在層次化程序設計中,上層模塊可以直接調用下層模塊的函數,而下層模塊一般不能直接調用上層模塊的函數。而實際情況中卻常常存在層間相互依賴的情況,即層間相互調用函數,例如,層B的狀態變化需要通知層A或者引起層B的狀態變化,為了避免這種相互依賴,可以使用回調函數。假設層A位於層B的上層,層A調用層B的函數,稱層A為caller,層B中被調用的函數被稱為callee,層A中被callee回調的函數稱為callbacker。

1. 回調函數

回調函數是通過caller向callee傳遞callbacker的函數指針實現,當在callee中callbacker被調用時,稱為發生回調,而callbacker則稱為回調函數。callee無需關心callbacker的實現細節和所處理的具體的數據類型,僅需知道callbacker的原型即可,而callbacker的實現由caller負責,其中包括實現細節(算法)和數據類型。

回調函數可以實現動態綁定,即通過在運行時向callee傳遞不同的函數指針,從而調用不同的函數。例如,排序算法中需要按某種規則比較數據,callee無需知道數據比較的方法以及數據的類型,而僅僅關心比較數據的個數以及比較結果的含義,具體的比較操作由callbacker負責,數據類型可以是原始數據類型也可以是結構體類型。

回調可以實現消息通知和事件驅動,比如callee中發生某個事件時,需要通知caller或者需要caller完成某種功能,則可以通過回調機制實現。

2. 函數指針

回調機制是通過傳遞函數指針實現,而函數指針則是指向函數的指針,函數指針的定義可以使用兩種形式:

(1)直接定義

函數返回類型 (*函數指針名)(形參表);

(2)使用typedef

typedef 函數返回類型 (*新類型名)(形參表);

新類型名 函數指針名;

int add_int(int a, int b){return a+b;}

int (*pfunc)(int x, int y);

pfun = add_int;//或者&add_int

typedef int (*PFUNC)(int x, int y);

PFUNC pfunx;

pfunx = &add_int;

3. 返回函數指針的函數

即函數的返回值是一個函數指針,也可以有兩種定義形式:

(1)直接定義

函數返回類型 (*函數名(形參表1))(形參表2){......}

定義了一個名稱由“函數名”標識的函數,其參數由“形參表1”標識,該函數返回一個函數指針,指向一個由“函數返回類型”標識返回類型、參數個數以及類型符合“形參表2”的函數。

(2)使用typedef

typedef 函數返回類型 (*新類型名)(形參表2);

新類型名 函數名(形參表1){......}

實例:

void (*signal(int sig, void (*func)(int)))(int);

函數名:signal

功能:指定處理信號的函數,sig指定信號,func為處理該信號的函數,具有一個整型的參數

返回值:為一個函數指針,指向一個具有一個整型參數、返回值類型為void的函數,該函數參數類型以及返回值類型與func函數一致;即返回該信號之前的處理函數

#include <signal.h>

char tmpfilename [L_tmpnam];

void terminate (int param)
{
printf ("Terminating program...\n");
remove (tmpfilename);//移除臨時文件
exit(1);
}

int main(void)
{
void (*prev_fn)(int);//定義函數指針
FILE *fp;

prev_fn = signal (SIGTERM,terminate);//為SIGTERM信號指定處理函數terminate

tmpnam (tmpfilename);//生成臨時文件名並保存在tmpfilename中

fp = fopen(tmpfilename, "w+");
fprintf(fp, "test");
fclose(fp);

raise(SIGTERM);//生成SIGTERM信號並通知進程

if (prev_fn==SIG_IGN) signal (SIGTERM,SIG_IGN);//重新設定默認處理函數

return 0;
}

4. 函數指針數組

指向一組有相同返回類型以及參數個數和順序的函數,常用來替換switch/if結構,也可以有兩種定義形式:

(1)直接定義

函數返回類型 (*函數指針數組名[N])(形參表);

(2)使用typedef

typedef 函數返回類型 (*新類型名)(形參表);

新類型名 函數指針數組名[N];

Copyright © Linux教程網 All Rights Reserved