关于函数指针的声明

时间:2018-11-20 13:28:38

标签: c function-pointers

我正在考虑以下两者之间的区别:

void *signal(int, void (*)(int))(int)

void (*signal(int, void (*)(int)))(int)

我知道后者来自here - Example #3: The ``Ultimate''(当我尝试大声说出以了解它时,这是一种有趣的学习经历):

  

signal是一个以(int, void (*)(int))作为输入并返回指向另一个函数的指针,该函数使用(int)并返回void

对于前者,我认为自上一个(int)起优先于*,因此它应该是语法错误,但是从cdecl.org起,结果是:

[“]将信号声明为函数(int,返回指向void的函数(int)的指针)返回函数(int)返回指向void [。”的指针。

所以我需要检查。

2 个答案:

答案 0 :(得分:6)

必须区分语法和语义。 cdecl.org仅提供您在其中键入的任何声明符的语法含义。在第一个示例中,确实确实有signal语法上正确的声明作为返回函数的函数。但是,C不允许函数返回其他函数:

  

N1570 6.7.6.3§1:

     

函数声明符不得指定函数类型或数组类型的返回类型。

因此,尽管该声明在语法上是正确的,但在语法上是无效的。换句话说:尽管C语法使编写“函数返回函数”成为可能,但实际上不允许您在程序中具有返回函数的函数。就像英语(或与此有关的任何一种语言)一样,您也可以表达各种实际上无法实现的想法……

答案 1 :(得分:1)

这里最重要的部分是...您不需要学习它,这是该语言中设计不良的部分。您可以向下滚动到答案的底部以找到理智,专业的解决方案。

否则,如果您坚持要这样做的话...


当试图从一个函数返回一个函数指针时,该函数指针的类型会被拆分。如果要返回函数指针void(*)(void),则此不良函数指针将分为3部分。让我们这样称呼他们:

  • void是A,是指向函数的返回类型。
  • (*)是B,将其标记为指向函数而不是函数的指针。
  • (void)是C,是指向函数的参数。

然后,如果我们要将其作为返回类型粘贴到其他一些icky函数声明中,则它们最终将像这样:

#define A void
#define B *
#define C (void)

// A (B) C equals void(*)(void)

A (B madness(int, void (*fp)(int))) C;

其中A,B和C是要返回的不良函数指针的一部分,madness是函数的名称,其余是函数本身用作参数的混乱情况。

如果我们省略B部分,它将被解释为一个函数,它返回另一个void f (void);类型的无效函数。语法允许它,但不允许语言规范。

类似地,int foo (void) [3];-返回数组的函数也不允许。


思考这些事情是通往疯狂的道路,它使代码不可读。专业程序员使用typedef

给出

void (*madness(int, void (*f)(int)))(int);

替换为:

typedef void func_t (int);

func_t* sanity (int, func_t* f);