如何理解这个定义

现在,我正在阅读APUE。我发现这个函数定义如下:

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

我很困惑,我知道信号是指向一个函数,最后(int)是他的参数。 我不知道是什么(int signo,void(* func)(int))。

Solutions Collecting From Web of "如何理解这个定义"

一般程序:找到最左边的标识符,并按照你的出路。 如果没有使用括号的明确分组,像()[]这样的后缀运算符在一元运算符如*之前绑定。 因此,以下都是真实的:

 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示例代码,希望更多的说明。

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

信号是一个函数,它接受int和一个指向int的函数,并返回void,返回一个带int和返回void的函数指针。 那是,

 typedef void(*funcPtr)(int) 

那么我们有

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

语法确实很奇怪,用typedef最好做这样的事情。 作为一个例子,如果你想声明一个函数,它接受一个int并返回一个指向一个函数的指针,而返回double将会是

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

编辑:在读了“Wooooooow”的评论后,我提供了另一个更“woooow”的例子:)

我们来声明一个函数
1.一个指向数组指针数组的指针,每个函数每个都有浮点数并返回double。
2.一个指向3个指向4个数组的指针的指针
并返回一个指向函数的指针,该指针指向函数的指针,并返回一个指向浮点函数的指针,返回void并返回unsigned int。

typedef解决方案将是这样的:

 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); 

现在,有趣的部分:) 没有typedefs这将是

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

我的天啊,我只是写这个吗? 🙂

顺时针螺旋规则将有助于: http : //c-faq.com/decl/spiral.anderson.html

有三个简单的步骤:

以未知元素开始,以螺旋/顺时针方向移动; 当生成以下元素时,用相应的英语语句替换它们:

[X]或[] =>数组X的大小…或数组未定义的大小…

(type1,type2)=>函数传递type1和type2返回…

  • =>指向…的指针

继续以螺旋/顺时针方向进行操作,直到所有的令牌都被覆盖。 总是先解决任何括号内的问题!

参见“Example#3:'Ultimate'”,这几乎就是你所要求的:

“信号是一个函数传递一个int和一个指向函数的指针传递一个int返回什么(void)返回一个指向函数的指针传递一个int什么也不返回(void)”

如果你现在还没有访问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 

这个网站给C的胡言乱语:

C乱码< – >英文

为你的发行版安装cdecl (如果有的话)或去这里

否则,我相信阿明Tsirunyan的答案是正确的。