原文連接:http://blog.csdn.net/baishuwei/article/details/3210810安全
今天與幾個同窗看到了一個函數指針定義:函數
void (*f(int, void (*)(int)))(int)spa
之前在C trap pit fails裏面見過,可是文章裏面介紹的很詳細,可是每每使初學者抓不到重點, 結果弄的一頭污水。這裏就簡單介紹一下這中函數指針的定義方法。.net
這個問題從定義的角度來看很好理解,指向函數的指針就是函數指針,可是咱們如何聲明一個函數指針呢?又如何將一個地址強制轉換爲某一個類型的函數指針呢?這裏看下面一個例子源碼:指針
void function(int a)blog
{get
a = 5;源碼
}it
void (*pfunc)(int); io
很簡單,上面這段代碼聲明瞭一個函數fucntion和一個函數指針pfunc, 它指向的函數就是一個具備void返回值,int參數的函數。若是將function函數的地址給pfunc指針,能夠簡單的經過下面兩種賦值:
pfunc = function;
或者
pfunc = &function;
經過指針調用該函數,也有兩種方法:
pfunc(5); 或 (*pfunc)(5);
咱們看一下賦值語句,pfunc = function; 但有時候多是一個常數0x8999940, 它剛好也表示一個安全的與function相同的函數,如何將這個數值賦給pfunc呢?顯然咱們須要強制類型轉換,應該將該常數轉換成什麼類型呢?這就是問題的關鍵!
在void (*pfunc)(int)語句裏面,只有pfunc是變量名稱,那麼剩餘的部分,void(*)(int),就是咱們須要的轉換類型。所以,新的賦值語句是:
pfunc = (void (*)(int)) 0x8999940;
賦值完成後,就能夠經過pfunc(5); 或 (*pfunc)(5);調用相應的函數了。
若是理解了上面的內容,咱們就能夠解釋void (*signal(int, void (*)(int)))(int)這個相對複雜的問題了
如今咱們先拋開上面那個複雜的定義,先看一下下面的需求1) 定義一個函數;2) 該函數具備如下特色,兩個參數,返回值是函數指針,而且一個參數也是函數指針。假如返回值和參數函數指針同爲void (*)(int); 另外一個函數參數是int型。該函數定義名稱爲my_func。
根據需求咱們能夠很容易定義出這種函數:
typedef void (*HANDLER)(int); // 參數函數和返回函數定義
HANDLER my_func(int, HANDLER);
忽然需求中又不讓使用typedef,這就是早期C語言不支持typedef的狀況,那麼如何定義這種函數呢?
咱們假如說my_func的返回值是int,是否是它的定義能夠這麼寫:
int my_func(int, void (*)(int));
也就是說,my_func(int, void (*)(int))就是一個int型數據。如今將int換成一個函數,也就是
void (*)(int) my_func)(int, void (*)(int);
這樣一種定義,顯然這種語法不支持,那麼,實際是如何表示呢?回過頭來,咱們先看看函數指針的聲明格式
void (*pfunc)(int);
其中pfunc 等價於 void (*)(int)。如今在看看上面的格式,是否是很相識,對了,pfunc就是my_func(int, void (*)(int))。如今若是將二者代替一下是否是就成了這種格式:
void (*my_func(int, void(*)(int)))(int)
若是將my_func換成signal,是否是就是咱們文章開始提到的那個複雜聲名?如今是否是明白了,原來如此啊,它是一個返回函數指針的的函數聲名!