我正在考虑以下两者之间的区别:
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 [。”的指针。
所以我需要检查。
答案 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);