2010-11-08 45 views
12

現在,我正在讀APUE.and我發現中定義的功能如下:如何理解這個定義

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

我很困惑,我知道信號是指向函數的指針和最後一個(INT)是他的參數。 我不知道什麼是(int signo,void(* func)(int))。

+1

獲取'cdecl'。它會告訴你所有這些事情。我會問:'void void(* signal(int,void(*)(int)))(int);'它會回答:'將信號聲明爲函數(int,指向函數的指針(int)返回void)函數(int)返回void' – 2010-11-08 10:57:15

+0

嘗試http://cdecl.org/ – 2010-11-08 13:09:28

回答

23

的一般程序:找到最左邊的標識符並按照你的方式工作。如果沒有使用圓括號的明確分組,後綴運算符(如()[])在諸如*之類的一元運算符之前綁定;因此,下面都是真:

T *x[N]    -- x is an N-element array of pointer to T 
T (*x)[N]   -- x is a pointer to an N-element array of T 
T *f()    -- f is a function returning a pointer to T 
T (*f)()   -- f is a pointer to a function returning T 

應用這些規則的聲明後,它打破了作爲

 signal          -- signal 
     signal(       )  -- is a function 
     signal( signo,     )  -- with a parameter named signo 
     signal(int signo,     )  -- of type int 
     signal(int signo,  func  )  -- and a parameter named func 
     signal(int signo,  *func  )  -- of type pointer 
     signal(int signo,  (*func)( ))  -- to a function 
     signal(int signo,  (*func)(int))  -- taking an int parameter 
     signal(int signo, void (*func)(int))  -- and returning void 
     *signal(int signo, void (*func)(int))  -- returning a pointer 
    (*signal(int signo, void (*func)(int)))( ) -- to a function 
    (*signal(int signo, void (*func)(int)))(int) -- taking an int parameter 
void (*signal(int signo, void (*func)(int)))(int); -- and returning void 

總之,signal返回一個指向返回void功能。 signal需要兩個參數:一個整數和指向另一個函數的指針,返回void

你可以使用typedefs使它更易於閱讀(而Ubuntu的linux上的signal的手冊頁就是這麼做的);不過,我認爲展示非typedef'd版本來演示語法的工作方式是很有價值的。 typedef工具非常棒,但您真的需要了解底層類型如何工作纔能有效地使用它。

signal函數設置了一個信號處理程序;第二個參數是在接收到信號時要執行的功能。返回指向當前信號處理程序(如果有的話)的指針。

例如,如果你希望你的程序來處理中斷信號(如按Ctrl-C):

static int g_interruptFlag = 0; 

void interruptHandler(int sig) 
{ 
    g_interruptFlag = 1; 
} 

int main(void) 
{ 
    ... 
    /** 
    * Install the interrupt handler, saving the previous interrupt handler 
    */ 
    void (*oldInterruptHandler)(int) = signal(SIGINT, interruptHandler); 

    while (!g_interruptFlag) 
    { 
    // do something interesting until someone hits Ctrl-C 
    } 

    /** 
    * Restore the previous interrupt handler (not necessary for this particular 
    * example, but there may be cases where you want to swap out signal handlers 
    * after handling a specific condition) 
    */ 
    signal(SIGINT, oldInterruptHandler); 
    return 0; 
} 

編輯我延長了示例代碼signal的東西,就是希望更多的說明。

+1

+1獲得精彩的答案! – Shrayas 2012-10-12 06:51:20

16
void (*signal(int signo, void (*func)(int)))(int); 

signal是一個函數,它接受int和一個指向函數的指針,取int和返回void並返回一個帶int和返回void的函數指針。也就是說,

typedef void(*funcPtr)(int) 

那麼我們有

funcPtr signal(int signo, funcPtr func); //equivalent to the above 

語法的確是怪了,這樣的事情最好是用一個typedef來完成。舉個例子,如果你要聲明一個函數,它接受一個int並返回一個指向函數取char和雙回將

double (*f(int))(char); 

編輯:評論,上面寫着「Wooooooow」後,我我提供了另一個更「例外」的例子:)

讓我們聲明一個函數,其中需要
1.一個指向數組指針的數組,指向每個函數,每個函數使用float和返回double。
2.一個指向數組3個指數到4個數組的指針
並返回一個指向函數的指針,該指針接受一個指向函數的指針,返回一個指向函數的指針,並返回void並返回unsigned int。

的類型定義的解決辦法是這樣的:

typedef double (*f1ptr) (float); 
typedef f1ptr (*arr1ptr)[5]; 
typedef int (*arr2ptr)[4]; 
typedef arr2ptr (*arr3ptr)[3]; 
typedef void(*f2Ptr)(float); 
typedef f2ptr (*f3ptr)(int); 
typedef unsigned int (*f4ptr) (f3ptr); 
f4ptr TheFunction(arr1ptr arg1, arr3ptr arg2); 

現在,有趣的部分:) 沒有類型定義,這將是

unsigned int (*TheFunction(double (*(*)[5])(float), int(*(*)[3])[4]))(void(*(*)(int))(float)) 

我的天啊,我剛寫的是什麼? :)

+2

Wooooooooooooow – valdo 2010-11-08 12:59:30

+0

@valdo:看到我的編輯更壞wooooow :) – 2010-11-08 13:19:31

+0

有趣嗎?非typedef'd版本*完全*透明。 – 2010-11-08 13:38:54

12

順時針螺旋規則將幫助: http://c-faq.com/decl/spiral.anderson.html

有三個簡單的步驟如下:

與未知元素開始,以螺旋/順時針方向移動; ecountering以下元素時與相應的英文語句代替它:

的...或數組的大小未定義

[X]或[] =>數組X大小...

(TYPE1,TYPE2)= >功能通過Type1和Type2返回...

  • =>指針(多個)爲...

保存,直到所有令牌已被被覆蓋在螺線/順時針方向這樣做。 總是先解決括號中的任何內容吧!

參見「示例#3:‘終極’」,這是相當多的,你問什麼了:

「信號傳遞一個int和指針的函數傳遞一個int功能返回無(無效)返回一個指針的函數傳遞一個int返回什麼(無效)」

+0

這是一個非常漂亮的資源。謝謝 ! – Shrayas 2012-10-12 07:01:23

0

爲您配送安裝cdecl(如有)或去here

否則,我相信阿爾緬Tsirunyan的答案是正確的。

3

如果您沒有訪問cdecl現在,這裏是CDECL輸出:

$ cdecl 
cdecl> explain void (*signal(int , void (*)(int)))(int); 
declare signal as function (int, pointer to function (int) returning void) returning pointer to function (int) returning void