关于函数指针的声明

About a declaration of function pointer

我在思考两者的区别:

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

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

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

signal is a function takes (int, void (*)(int)) as input and returns a pointer to another function that takes (int) and returns void.

对于前者,我认为由于最后一个 (int) 的优先级高于 * 所以它应该是一个语法错误,但是从 cdecl.org 结果是:

["] declare signal as function (int, pointer to function (int) returning void) returning function (int) returning pointer to void [."]

所以我需要支票。

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

N1570 6.7.6.3 §1:

A function declarator shall not specify a return type that is a function type or an array type.

因此,虽然此声明语法 正确,但语义 无效。换句话说:虽然 C 语法使编写“函数 return 函数”成为可能,但您实际上不允许在程序中具有 return 函数的函数。就像英语(或与此相关的任何语言)也可以让你表达各种各样的想法,而这些想法在身体上是不可能实现的……

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

不然的话,硬要是这样……


尝试从函数 return 函数指针时,函数指针的类型被拆分。如果你想 return 一个函数指针 void(*)(void),那么这个可怜的函数指针会被分成 3 部分。让我们这样称呼它们:

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

然后如果我们想将它作为 return 类型粘贴到其他一些讨厌的函数声明中,它们最终会像这样:

#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 是我们要 returned 的可怜的函数指针的部分,madness 是函数的名称,其余部分是用作参数的一些乱七八糟的东西函数本身。

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

同样,int foo (void) [3]; - 函数 return 数组也是不允许的。


琢磨这些东西是疯子之路,它使代码变得不可读。专业程序员使用typedef.

给定

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

替换为:

typedef void func_t (int);

func_t* sanity (int, func_t* f);