2010-11-08 43 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