在C+;中递归到main()合法吗+;? < >我读到C++标准禁止在()/中递归,但是g++编译下列代码无需抱怨: int main() { main(); }

在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

有人能澄清这一点吗?

根据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 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]