【问题标题】:Two questions on main两个主要问题
【发布时间】:2011-04-09 12:31:52
【问题描述】:

A.以下尝试定义 C++ 独立程序的入口点“main”是否有效?

namespace{
 extern int main(){return 0;}
}

据我了解,它满足 C++ 标准中关于“main”的所有标准(外部链接,由于隐含的 using 指令,可在全局命名空间中使用)。

那么这个程序格式不正确,为什么?有没有参考标准?

B.我已经对 EXIT_FAILURE 和 EXIT_SUCCESS 进行了讨论,但无法得出 EXIT_SUCCESS 是否应该始终为 0 的结论。这是因为根据标准,在“main”中省略 return 语句相当于返回 0。所以我想,EXIT_SUCCESS 应该总是0.

$18.3 - “如果状态为零或 EXIT_SUCCESS,则返回状态成功终止的实现定义形式。”

【问题讨论】:

    标签: c++ namespaces main


    【解决方案1】:

    这里,namespace { } 是一个匿名命名空间 - 其想法是任何东西都不应从那里逃逸到全局命名空间中 - 实际上,它都应该以不会与其他翻译单元冲突的东西作为前缀。你做了extern,但不是extern "C",所以关于 main 不被破坏的特殊规则不会保护它,并且符号不会满足链接要求。无论如何,将一些 extern 放在匿名命名空间中只是一种混乱的想法。您始终不遗余力地查看如何将标准扭曲成奇怪的扭曲:-)。很好奇 - 有什么原因吗?您是在学术上对此感兴趣,还是对编译器或编译器测试套件或其他东西感兴趣?

    看到您在问题中添加了关于 EXIT_SUCCESS 和 EXIT_FAILURE 的讨论。这里的关键点是您可以从 main 或 exit() 使用它们,并且知道它们可以在任何操作系统上运行。对于返回 0,无论您使用 EXIT_SUCCESS、0 还是让 main “失败”都不是问题。操作系统实际上可能会或可能不会将 0 返回给操作系统……可能是运行时将其映射到其他值,这意味着该操作系统上的“成功”。但是,对于失败 - 如果您返回一个任意的非 0 值,它可能会绕过该映射,并且要么指示与简单失败不同的东西,要么恰好与成功值一致。在不同的操作系统上,值也可以有不同的处理方式:许多(例如 Linux)会去除除 8 个最低有效位之外的所有返回值,这样返回 256 就等于返回 0。这就是为什么猜测不是一个好主意在一个合适的非 0 值。

    【讨论】:

    • 在阅读 en.wikipedia.org/wiki/Main_function_(programming) 时,声明“Sun Studio 11 C++ 编译器允许在非全局命名空间中使用 main 并作为(类或实例)成员函数。”引发了这种想法。
    • 我不喜欢任何与标准/编译器/编译器测试套件等相关的东西,尽管我很乐意。我只是对 C++ 充满热情
    • 好吧,维基百科的那段开头“main 必须在全局命名空间(即 ::main)中,并且不能是(类或实例)成员函数,尽管名称不是保留的,并且可能是用于其他(普通)成员函数或非成员函数。Sun Studio 11 C++ 编译器..."。听起来很像他们在说 Sun 允许标准的例外。
    • 维基百科不是我通常的标准一致性信息来源。
    【解决方案2】:

    A.以下尝试定义 C++ 独立程序的入口点“main”是否有效?

    没有。 C++ 标准说“程序应包含一个名为 main 的全局函数”(第 3.6.1/1 节)。在您的程序中,main 函数不在全局命名空间中;它位于一个未命名的命名空间中。

    隐式 using 指令只允许在封闭的命名空间中查找和使用来自未命名命名空间的名称;它不会将这些名称添加到封闭的命名空间中。具体来说,“using-directive 不会将任何成员添加到它出现的声明性区域”(第 7.3.4/1 节)。

    这个程序格式不正确,为什么?

    程序不一定是格式错误的。没有规则禁止在全局命名空间以外的命名空间中使用名为 main 的函数;这样的功能不是 main 功能。 namespace { int main(); } 和 int main() 是两个不同的函数,一个格式良好的程序可以同时拥有这两个函数。

    请注意,如果您的程序在全局命名空间中没有 main 函数,则该程序是非良构的(因为如上所述,托管环境中的程序必须具有 main 函数)。

    B.我已经对EXIT_FAILURE 和EXIT_SUCCESS 进行了讨论,但无法确定EXIT_SUCCESS 是否应该始终为0。

    不要求EXIT_SUCCESS 扩展为0。 C 标准简单地说,在<stdlib.h>,

    定义的宏是...EXIT_FAILURE 和EXIT_SUCCESS,它们扩展为整数常量表达式,可用作exit 函数的参数,分别向主机环境返回不成功或成功终止状态(C99 §7.20/3)。

    (由于这两个宏是在<cstdlib> 中定义的,因此C 标准包含了它们的规范)。

    【讨论】:

    • 看,这就是我永远知道的;入口点(至少在 C/C++ 中)是一个名为 main 的 global 函数。然而,在 C++ Primer, 4th edition 的第 717 页,它说“编写一个程序……使该程序成为另一个名称空间的成员……”什么?!这就是为什么我尝试了它(不成功)并在查找时出现在这里。
    • @Synetech:另见What is the proper declaration of main?。我对main() 函数的讨论比任何人真正关心的都要详细。
    • 是的,这个答案描述了我长期以来所知道的。尽管如此,这本书指出读者将程序(例如 main())放在一个命名空间中以进行该练习。我已经检查过,勘误表中没有提到它,所以我不确定它是否意味着编译或运行,而只是使用命名空间的练习。
    【解决方案3】:

    A.当我尝试在 Visual C++ 2010 中运行您的代码时,我得到了这个:

    错误 1 ​​错误 LNK1561:入口点 一定是 定义

    在 C++ 中,main 必须在全局命名空间(即 ::main)中,并且不能是(类或实例)成员函数,尽管名称不是保留的,并且可以用于其他(普通)成员函数或非成员函数。

    退出状态

    从main返回的值 函数成为退出状态 该过程,尽管 C 标准 仅将特定含义归因于两个 值:EXIT_SUCCESS(传统上 零)和EXIT_FAILURE。的含义 其他可能的返回值是 实现定义。

    更多信息here。

    【讨论】:

    • 是的,这是我正在阅读的网站,它引发了这个问题(我在托尼的帖子中的 cmets)。
    • from §3.6.1/2, "This function shall not be overloaded.", 所以实际上“可能用于其他 xxx 或非成员函数”不太正确(我看到你从维基百科复制的...有风险的;-))。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    • 2010-12-25
    • 2011-02-07
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 2020-08-10
    相关资源
    最近更新 更多