关于函数指针的声明
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);
我在思考两者的区别:
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 returnsvoid
.
对于前者,我认为由于最后一个 (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);