45

我读到 C++ 标准禁止在 中递归main(),但 g++ 编译以下代码没有任何抱怨:

int main()
{
    main();
}

任何人都可以澄清这一点吗?

4

5 回答 5

49

根据 3.6.1/3 中的标准,它不是:

该功能main 不得在程序中使用 (3.2)

used being的定义:

如果对象或非重载函数的名称出现在可能求值的表达式中,则使用该对象或非重载函数。

于 2010-12-23T12:11:22.113 回答
37

我会做鱼并解释为什么这是禁止的。在 C 或 C++ 程序可以开始运行之前,必须首先初始化 CRT。打开 stdin/out/err,调用初始化程序,诸如此类。有两种基本策略可以完成这项工作,一个是繁重的平台实现细节。

  • 程序的起始地址指向 CRT init 函数,该函数最终调用 main()。在功能齐全的操作系统上很常见,这些操作系统有一个花哨的加载器,可以支持可执行映像中的任意部分。

  • 编译器将代码注入到调用 CRT 初始化函数的 main() 函数中。启动函数始终是 main()。在加载器功能有限的嵌入式平台上很常见。递归 main() 现在是一个问题,CRT 启动代码将被再次调用,堆栈状态不可预测。

于 2010-12-23T14:01:35.823 回答
22

这里的说法是它确实是明确禁止的:

好吧,标准规定:

3.6.1.3
“函数 main 不得在程序中使用。”

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;
}

(注意我添加了一个退出子句。我什至不能假设编码无限递归,它在我身上重复。)

于 2010-12-23T12:13:39.440 回答
9

这是不合法的。阅读 3.6.1-3:

函数 main 不得在程序中使用(3.2)。main 的链接(3.5)是实现定义的。将 main 声明为 inline 或 static 的程序是格式错误的。名称 main 没有保留。[示例:成员函数、类和枚举可以称为 main,其他命名空间中的实体也可以。]

于 2010-12-23T12:14:16.583 回答
1

其他人已经解决了标准部分。但是,我想指出,如果您使用-pedantic-errors这些错误中的至少一个(取决于main签名),g++(至少 4.6.2)将拒绝此操作:

error: ISO C++ forbids calling ‘::main’ from within program [-pedantic]
error: ISO C++ forbids taking address of function ‘::main’ [-pedantic]
于 2012-03-04T12:36:35.073 回答