我应该从 main() 返回 EXIT_SUCCESS 还是 0?
Posted
技术标签:
【中文标题】我应该从 main() 返回 EXIT_SUCCESS 还是 0?【英文标题】:Should I return EXIT_SUCCESS or 0 from main()? 【发布时间】:2019-10-01 10:59:00 【问题描述】:这是一个简单的问题,但我一直看到相互矛盾的答案:C++ 程序的主例程应该返回0
还是EXIT_SUCCESS
?
#include <cstdlib>
int main()return EXIT_SUCCESS;
或
int main()return 0;
它们是完全一样的吗? EXIT_SUCCESS
应该只与exit()
一起使用吗?
我认为EXIT_SUCCESS
会是更好的选择,因为其他软件可能希望将零视为失败,但我还听说如果您返回0
,编译器无论如何都能够将其更改为不同的值。
【问题讨论】:
This answer about C90 解释了标准——0
和 EXIT_SUCCESS
都被解释为成功。
我会在这里回复,因为我觉得将来会有其他人阅读此内容。基本上有很多关于“正确 C”的范式。一些范例更喜欢使用字面量而不是宏,例如,不是将 NULL 作为参数传递,它们可能会传递 (const char *)0 来指示它不仅仅是一个空值,但如果它不是空值,它应该是一个常量字符指针。其他范例更喜欢与类型无关,并且通过使用宏类型,它们可以避免在事情发生根本变化时更改其代码库。例如,许多 -
@Dmitry 你从一个程序返回的只是一个约定。
不,我想不出“EXIT_SUCCESS”不会为“0”的任何情况。
我个人推荐“0”。
恕我直言...
【讨论】:
我已经用 C++ 编程 10 年了,仍然不记得在返回值方面 0 是代表成功还是失败。 @lahjaton_j 我明白了。它认为这是因为它违反直觉:0
是错误的,许多函数在失败/什么都不做时返回 0
。【参考方案2】:
如果您使用 EXIT_SUCCESS,您的代码将更具可移植性。
http://www.dreamincode.net/forums/topic/57495-return-0-vs-return-exit-success/
【讨论】:
我非常怀疑它是否会使您的代码更便携或更不便携。 不,不会。该标准保证 0 和EXIT_SUCCESS
都表示成功终止。
如果你说“如果你使用 use EXIT_FAILURE
,你的代码会更便携”,那就对了。【参考方案3】:
没关系。两者都是一样的。
C++ 标准引用:
如果 status 的值为 0 或 EXIT_SUCCESS,则返回实现定义的状态成功终止形式。
【讨论】:
这对编译器来说无关紧要,但作为风格问题可能很重要。 @celtschk:风格问题是基于感知的,也就是非标准化,因此这不算作差异。您只能将苹果与苹果进行比较,而不能将苹果与梨进行比较。 不保证EXIT_SUCCESS == 0
。另一方面,没有充分的理由不这样做。
@PravasiMeet:一个系统可能有多个值表示成功。
功能重于形式,但清晰重于功能。我可以从专业经验告诉你,风格在编程中非常重要。【参考方案4】:
一些编译器可能会产生问题 - 在 Mac C++ 编译器上,EXIT_SUCCESS 对我来说工作得很好,但在 Linux C++ 编译器上,我必须添加 cstdlib 才能知道 EXIT_SUCCESS 是什么。除此之外,它们是一回事。
【讨论】:
我的意思是在 Mac 上 EXIT_SUCCESS 在不包含 cstdlib 的情况下工作。 如果EXIT_SUCCESS
在不包含<stdlib.h>
或<cstdlib>
的情况下工作,则必须有其他标头直接或间接定义了它。在 C++ 中,标准头文件到 #include
其他标准头文件是很常见的。如果编译没有错误:int main() return EXIT_SUCCESS;
那么你的编译器可能有问题。【参考方案5】:
根据定义,0 是一个幻数。 EXIT_SUCCESS 几乎普遍等于 0,很高兴。那么为什么不直接返回/退出 0 呢?
退出(EXIT_SUCCESS);含义非常明确。
退出(0);另一方面,在某些方面是违反直觉的。不熟悉 shell 行为的人可能会认为 0 == false == 不好,就像 C 中 0 的所有其他用法一样。但不是 - 在这种特殊情况下,0 == 成功 == 好。对于大多数有经验的开发人员来说,这不会是一个问题。但是,为什么要无缘无故地绊倒新人呢?
tl;dr - 如果为您的幻数定义了一个常量,那么几乎没有理由不首先使用该常量。它更易于搜索,通常更清晰等,而且不会花费您任何费用。
【讨论】:
我认为您的 cmets 关于人们期望 0 自动变坏的说法是错误的。很多 API 使用 0 表示成功,使用非 0 表示失败,即使在 stdlib 中也是如此。例如。 stdlib (fclose()
, setvbuf()
, ...), POSIX (listen()
, pthread_create()
, pipe()
, ...) 和许多,许多 其他库(例如 OpenGL [glGetError()
]、zlib [deflate()
/inflate()
/...]、SDL [SDL_CreateWindowAndRenderer()
/...] 等)。
当然,还有其他情况下 0 用于表示“成功”,但他说得对,这让人困惑。【参考方案6】:
EXIT_FAILURE
,无论是在main
的return 语句中还是作为exit()
的参数,都是在C 或C++ 程序中指示失败的唯一可移植方式。例如,exit(1)
实际上可以在 VMS 上发出成功终止的信号。
如果您要在程序失败时使用EXIT_FAILURE
,那么您不妨在程序成功时使用EXIT_SUCCESS
,只是为了对称。
另一方面,如果程序从不发出失败信号,您可以使用0
或EXIT_SUCCESS
。标准保证两者都是成功完成的信号。 (EXIT_SUCCESS
几乎不可能有 0 以外的值,但在我听说过的每个实现中它都等于 0。)
使用0
有一个次要优势,即您在C 中不需要#include <stdlib.h>
,或者在C++ 中不需要#include <cstdlib>
(如果您使用return
语句而不是调用exit()
)——但是对于任何重要规模的程序,无论如何您都将直接或间接地包含 stdlib。
就此而言,在从 1999 年标准开始的 C 以及所有版本的 C++ 中,到达main()
的末尾无论如何都会隐含return 0;
,因此您可能不需要使用0
或@ 987654338@ 明确。 (但至少在 C 语言中,我认为明确的 return 0;
是更好的风格。)
(有人问及OpenVMS。我很久没用了,但我记得奇数状态值通常表示成功,偶数值表示失败。C 实现将0
映射到1
,因此return 0;
表示终止成功。其他值不变传递,因此return 1;
也表示终止成功。EXIT_FAILURE
将有一个非零偶数值。)
【讨论】:
当exit(0)
映射到退出状态 1 时,怎么可能为 OpenVMS 实现 POSIX 实用程序? (如果我正确理解你的最后一段)
@Rhymoid:这是由 C 指定的,而不是 POSIX。
@DeanP: 0
和 EXIT_SUCCESS
不能保证具有相同的值(我在回答中提到过),但它们都表示成功终止。 EXIT_SUCCESS
在风格上更好如果你也在使用EXIT_FAILURE
,但exit(0)
没问题。
这是个人的(出于相同的动机:明确),但我喜欢“返回(0)”(或!= 0),因为 shell 脚本“$?”兼容性(大多数 unix 程序返回 "$?"=0 表示成功)。
@AndréA.G.Scotá:POSIX 保证 EXIT_SUCCESS==0
。 (而且你不需要在 return
语句上加上括号。就我个人而言,我认为它们让它看起来太像函数调用了。)【参考方案7】:
一旦您开始编写可以返回无数退出状态的代码,您就可以开始#define
'ing 所有这些状态。在这种情况下,EXIT_SUCCESS
在不是“magic number”的情况下是有意义的。这使您的代码更具可读性,因为其他所有退出代码都是EXIT_SOMETHING
。如果您只是编写一个完成后将返回的程序,return 0
是有效的,并且可能更简洁,因为它表明没有复杂的返回代码结构。
【讨论】:
【参考方案8】:这是一个永无止境的故事,反映了“互操作性和可移植性”的局限性(一个神话)。
程序应该返回什么来表示“成功”应该由接收值的人(操作系统或调用程序的进程)定义,而不是由语言规范定义。
但程序员喜欢以“可移植方式”编写代码,因此他们为定义要返回的符号值的“操作系统”概念发明了自己的模型。
现在,在多对多场景中(许多语言用于向许多系统编写程序),“成功”的语言约定与操作系统之间的对应关系(没有人可以授予始终是同样)应该由特定目标平台的库的特定实现来处理。
但是 - 不幸的是 - 这些概念在部署 C 语言(主要用于编写 UNIX 内核)时并没有那么清楚,并且写成“返回 0 表示成功”的书籍的 Gigagrams,因为那是真的当时的操作系统有一个 C 编译器。
从那时起,就再也没有关于如何处理此类通信的明确标准。 C 和 C++ 对“返回值”有自己的定义,但没有人授予正确的操作系统翻译(或者更好:没有编译器文档对此有任何说明)。 0 表示成功,如果对于 UNIX - LINUX 和 - 出于独立的原因 - 对于 Windows 也是如此,这涵盖了 90% 的现有“消费者计算机”,在大多数情况下 - 忽略返回值(所以我们可以讨论了几十年,但没人会注意到!)
在这种情况下,在做出决定之前,请询问以下问题: - 我是否有兴趣向来电者传达一些关于我现有的信息? (如果我总是返回 0 ......所有事情背后都没有线索) - 我的来电者是否有关于此通信的约定? (请注意,单个值不是约定:不允许任何信息表示)
如果这两个答案都不是,那么好的解决方案可能是根本不编写主要的 return 语句。 (并让编译器来决定,相对于目标是如何工作的)。
如果没有约定 0=成功满足大多数情况(如果符号引入约定,则使用符号可能会有问题)。
如果有约定,请确保使用与其一致的符号常量(并确保平台之间的约定一致,而不是价值一致)。
【讨论】:
以上是关于我应该从 main() 返回 EXIT_SUCCESS 还是 0?的主要内容,如果未能解决你的问题,请参考以下文章