C23 中 int main() 和 int main(void) 等价原型吗?

chq*_*lie 18 c language-lawyer function-prototypes c23

C23 在函数声明符中引入了新的语义:

\n
\n

6.7.6.3 函数声明符

\n

[...]

\n

13\xc2\xa0\xc2\xa0\xc2\xa0对于没有参数类型列表的函数声明符:效果就像是使用由关键字 组成的参数类型列表进行声明void。函数声明符提供函数的原型。

\n
\n

这似乎意味着具有空参数列表的函数定义可以等效地用()or编写(void)

\n

然而,该函数似乎并不能保证这种main等价性:

\n
\n

5.1.2.2.1 程序启动

\n

程序启动时调用的函数名为main。该实现没有声明该函数的原型。它的返回类型应为int且不带参数定义:

\n
int main(void) { /* ... */ }\n
Run Code Online (Sandbox Code Playgroud)\n

或带有两个参数(此处称为argcargv,但可以使用任何名称,因为它们对于声明它们的函数来说是本地的):

\n
int main(int argc, char *argv[]) { /* ... */ }\n
Run Code Online (Sandbox Code Playgroud)\n

或等效的或以某种其他实现定义的方式。

\n
\n

这似乎并不能保证 是 的int main() { /* ... */ }有效定义main,或者等效定义是否涵盖此变体?

\n
\n

令我困扰的是,C17 中使用该语法int main()(6.5.3.4 和 6.7.6.3 中)的 2 个示例已更改为int main(void)在最新的 C23 草案中使用。

\n

Jon*_*ler 20

在 C17 及早期版本的标准中,int main() { \xe2\x80\xa6 }未提供原型main(),但在其他方面等效于int main(void) { \xe2\x80\xa6 }

\n

在 C23 中,int main() { \xe2\x80\xa6 }确实提供了 的原型,main()并且除了拼写之外,与 完全等效int main(void) { \xe2\x80\xa6 }

\n

main()仅当您递归调用 C 中允许而 C++ 中不允许的 \xe2\x80\x94 内容时,差异才有意义。在 C17 或更早版本中int main(),允许像这样的递归调用main(23, "elephants");,因为没有指定 的原型main()(假设 的定义main()在递归调用之前是可见的)。和int main(void),这是不允许的,因为作用域中有一个原型表示“无参数”。

\n

请注意C 和 C++ 中应该返回什么main()?中的内容。 这引起了广泛的讨论,包括 C17 和早期标准在其(非规范)示例中同时使用int main()和。int main(void)它还指出了微软为Windows系统指定的内容以及附件J“通用扩展”提到的内容(两者都认可int main(int argc, char **argv, char **envp))。main()Apple 甚至还有\xe2\x80\x94的第四个可选参数int main(int argc, char **argv, char **envp, char **apple),其行为类似于argvenvp。我需要尽快更新我对 C23 的答案。

\n

  • @CraigEstey 说的是一个_过时的_规则。Cfront 时代的 C++ 实现在“main”的开头注入代码来运行全局构造函数,并且该代码不是幂等的,因此递归调用“main”将再次运行全局构造函数,并且随之而来的是欢闹。我想这条规则至今仍然存在,很大程度上是因为 WG21 中没有人认为它重要到值得费心去改变。 (2认同)