在C+;中递归到main()合法吗+;? < >我读到C++标准禁止在()/中递归,但是g++编译下列代码无需抱怨: int main() { main(); }
有人能澄清这一点吗?根据3.6.1/3中的标准,它不是: 不得使用功能在C+;中递归到main()合法吗+;? < >我读到C++标准禁止在()/中递归,但是g++编译下列代码无需抱怨: int main() { main(); },c++,recursion,standards,main,C++,Recursion,Standards,Main,有人能澄清这一点吗?根据3.6.1/3中的标准,它不是: 不得使用功能main (3.2)在计划内 使用的定义是: 对象或非重载对象 如果函数名出现在可能计算的表达式中,则使用函数 这种说法是明确禁止的: 那么标准规定, 3.6.1.3 “主功能不得在程序中使用。” 5.2.2.9 允许递归调用,名为main的函数除外 当然,您可以这样做: int main(int argc, char* argv[]) { return foo(argc, argv); } int foo(int a
main
(3.2)在计划内
使用的定义是:
对象或非重载对象
如果函数名出现在可能计算的表达式中,则使用函数
这种说法是明确禁止的:
那么标准规定,
3.6.1.3
“主功能不得在程序中使用。” 5.2.2.9
允许递归调用,名为main的函数除外 当然,您可以这样做:
int main(int argc, char* argv[]) {
return foo(argc, argv);
}
int foo(int argc, char* argv[]) {
if (some_condition) {
return foo(argc, argv);
}
return 0;
}
(注意我添加了一个get out子句。我甚至不能假设编写无限递归,它在我身上重复。)这是不合法的。阅读3.6.1-3: 不得使用主功能 (3.2)在程序内。联系 (3.5)主要是 实现定义。一个程序 将main声明为内联或静态 他身体不好。名称main不是 另有保留。[示例:成员] 函数、类和枚举 可以称为main,也可以称为中的实体 其他名称空间。]
我来做鱼,解释为什么这是verboten。在C或C++程序可以开始运行之前,CRT必须先初始化。打开stdin/out/err,调用初始化器,诸如此类的东西。实现这一点有两种基本策略,一种是繁重的平台实现细节
- 程序的起始地址指向CRT init函数,该函数最终调用main()。在功能齐全的操作系统上很常见,这些系统有一个奇特的加载程序,可以支持可执行映像中的任意部分
- 编译器将代码注入调用CRT初始化函数的main()函数。start函数始终是main()。在加载程序功能有限的嵌入式平台上常见。递归main()现在是个问题,CRT启动代码将以不可预测的堆栈状态再次调用
-pedanticerrors
与至少一个错误(取决于main
签名)一起使用,g++(至少4.6.2)将拒绝此选项:
当然,这并不是经常强制执行的,因为它只在你做的编程不是很好的时候才有用。不,它确实需要诊断。见1.4/1和1.4/2。GCC是绝对错误的,有时甚至是。@Johannes:删除了说明GCC可能允许编译它的部分,感谢您的更正请参阅:@problemofficer如果编译了某些内容,并不意味着它是合法的。它可能是未定义的,然后任何事情都可能发生。@problemofficer:@VJo的评论是对marcog的评论的回应,他/她现在已经删除了该评论。(注释:如果编译,它必须是合法的,不是,或者是沿着这些线。)问题应该是“在C++中递归到主()是否合法?”@ Tyyk:<代码>无效()({Fe);}int int(){f-();}<代码>:你在<代码>主()/<代码>中重复吗?有些人会说“不”,有些人会说“是”。您是否正在递归到
main()
?没有人会说“是”。所以后者更清楚。你有参考资料吗?我看不出在main
中注入而不是在main
之前注入的任何原因。不管可执行格式是否允许任意起始地址,编译器都会生成机器代码,没有理由在它用作main
符号值的地址之后生成机器代码。@T.J.很难提供到实现详细信息的权威链接。但这个问题很好地说明了这一点:@Hans:谢谢。好吧,如果它是标准实践,并且是在像gcc这样的开源编译器中,我希望它是在某种模糊权威的地方编写的。我只是没有看到这一点,当然也没什么好的理由来把实现限制注入C++规范。我的意思是,他们显然有一个理由,他们不是哑巴,我只是想知道它是什么,因为我发现开始地址的论点不可信。“T.J.,如果你真的想知道,看看。”约翰尼斯:谢谢。这确实表明,根据系统架构,gcc可能会这样做。它没有说明原因(我仍然觉得它令人费解地落后),但就OP的问题和这个答案而言,它确实说明了这一点(这是公认的做法),这就是所需要的。再次感谢。没有递归是假设的,因为没有堆栈是无限的好的,如果您的函数是尾部递归的,并且编译器进行尾部调用优化(大多数情况下是这样),那么可以在不溢出堆栈的情况下导致无限递归;-)
error: ISO C++ forbids calling ‘::main’ from within program [-pedantic]
error: ISO C++ forbids taking address of function ‘::main’ [-pedantic]