1. 程式人生 > >函式指標&回撥函式&linux中的signal函式

函式指標&回撥函式&linux中的signal函式

1.

 int (*func)();函式指標,指向的函式為空引數,返回整型;

2.

回撥函式是一個程式設計師不能顯式呼叫的函式;通過將回調函式的地址傳給被呼叫者從而實現呼叫。

回撥函式是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用為呼叫它所指向的函式時,我們就說這是回撥函式。

    void f();// 函式原型

上面的語句聲明瞭一個函式,沒有輸入引數並返回void。那麼函式指標的宣告方法如下:

void (*) ();

    讓我們來分析一下,左邊圓括弧中的星號是函式指標宣告的關鍵。另外兩個元素是函式的返回型別(void)和由邊圓括弧中的入口引數(本例中引數是空)。注意本例中還沒有建立指標變數-只是聲明瞭變數型別。目前可以用這個變數型別來建立型別定義名及用sizeof表示式獲得函式指標的大小:

// 獲得函式指標的大小
unsigned psize = sizeof (void (*) ()); 

// 為函式指標宣告型別定義
typedef void (*pfv) ();

pfv是一個函式指標,它指向的函式沒有輸入引數,返回類行為void。使用這個型別定義名可以隱藏複雜的函式指標語法。

指標變數應該有一個變數名:

void (*p) (); //p是指向某函式的指標

    p是指向某函式的指標,該函式無輸入引數,返回值的型別為void。左邊圓括弧裡星號後的就是指標變數名。有了指標變數便可以賦值,值的內容是署名匹配的函式名和返回型別。例如:

void func() 
{
/* do something */

p = func; 

p的賦值可以不同,但一定要是函式的地址,並且署名和返回型別相同。



傳遞迴調函式的地址給呼叫者

    現在可以將p傳遞給另一個函式(呼叫者)- caller(),它將呼叫p指向的函式,而此函式名是未知的:

void caller(void(*ptr)())
{
ptr(); /* 呼叫ptr指向的函式 */ 
}
void func();
int main()
{
p = func; 
caller(p); /* 傳遞函式地址到呼叫者 */
}

    如果賦了不同的值給p(不同函式地址),那麼呼叫者將呼叫不同地址的函式。賦值可以發生在執行時,這樣使你能實現動態繫結。

3.函式指標在linux中的應用signal函式

在Unix/Linux中signal函式是比較複雜的一個,其定義原型如下: void (*signal(int signo,void (*func)(int))) (int) signal(int signo, void(*func)(int))是signal函式的主體. 需要兩個引數:int型的signo,以及一個指向函式的指標. void (*func)(int). 這個函式中,最外層的函式體 void (* XXX )(int)表明其返回值是一個指標(函式指標),指向一個函式XXX的指標,XXX所代表的函式需要一個int型的引數,返回void。 正是由於其複雜性,在[Plauger 1992]用typedef來對其進行簡化 typedef void Sigfuc(int);//這裡可以看成一個返回值 . 再對signal函式進行簡化就是這樣的了 Sigfunc *signal(int,Sigfuc *); 在signal.h標頭檔案中還有以下幾個定義 #define SIG_ERR (void (*)())-1 #define SIG_DFL (void (*)())0 #define SIG_IGN (void (*)())1