我应该从main()返回EXIT_SUCCESS还是0?


124

这是一个简单的问题,但是我不断看到矛盾的答案:C ++程序的主例程应该返回0还是EXIT_SUCCESS

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

要么

int main(){return 0;}

他们是一回事吗?如果EXIT_SUCCESS只使用exit()

我认为EXIT_SUCCESS这是一个更好的选择,因为其他软件可能希望将零视为失败,但是我还听说,如果返回0,则编译器仍然能够将其更改为其他值。


这回答了你的问题了吗?stackoverflow.com/questions/1188335/...
高炉

2
这是关于C90的答案复述标准- 0EXIT_SUCCESS都解释为成功。
ta.speot。是2012年

我会在这里回应,因为我认为将来会有其他人阅读。基本上,关于“正确的C”是什么样的。例如,某些范例更喜欢使用文字而不是宏,而不是传递NULL作为参数,它们可以传递(const char *)0来表示它不仅是null,而且如果不为null,则应为常量字符指针。其他范例更喜欢类型不可知,并且通过使用宏类型,可以避免在事物发生根本变化时更改代码库。例如,许多-
梅德

@Dmitry <续> Windows API类型定义在较新的平台上不正确,但是由于它们是宏,因此它们具有通过重新定义宏将所有类型更改为可以工作的类型的简便方法,并且其中许多类型仅通过定义进行缩放(例如int在不同平台上是不同的)。总而言之,如果返回码很重要并且将来可能会更改,请使用EXIT_SUCCESS之类的东西,否则返回0可能看起来像是个魔术数字,但这仍然是完全有效的标准约定。错误代码主要是为计划,以管数的结果从一个到另一个, -
梅德

@Dmitry <continued>使用错误代码调试程序有点弱,因为如果它确实返回0,则它是非常无用的信息,除非在某些情况下,如果程序中存在未经处理的未处理错误,这些错误会使程序无声地中断,则您需要检查它是否正常返回(0)或发生无提示错误。对于将0..255根据一个程序的输入从一个程序传递到另一个程序,返回数字更有用,否则就没有必要考虑它:返回0或使用预编译的main来内联无效的“ init”调用,而不是视觉上用无用的回报惹恼您。
德米特里

Answers:


150

EXIT_FAILURE在C或C ++程序中指示失败的唯一可移植方式是在in的return语句中main或作为in 的参数exit()exit(1)例如实际上可以在VMS上发出成功终止的信号。

如果要在EXIT_FAILURE程序失败EXIT_SUCCESS时使用,则在对称性方面也可能会在程序成功时使用。

另一方面,如果程序从不发出失败信号,则可以使用0EXIT_SUCCESS。标准均保证两者均表示成功完成。(几乎不可能EXIT_SUCCESS有一个非0的值,但在我听说过的每个实现中,该值都等于0。)

使用0具有#include <stdlib.h>C或#include <cstdlib>C ++中不需要的次要优点(如果使用的是return语句而不是调用exit()),但是对于任何大型程序,都将直接或间接包含stdlib无论如何。

因此,从1999年标准开始的C语言以及所有版本的C ++中,到达C语言的结尾都会main()隐式进行return 0;,因此您可能无需使用0EXIT_SUCCESS显式使用。(但至少在C语言中,我认为显式return 0;是更好的样式。)

(有人询问有关OpenVMS的问题。很长一段时间我都没有使用过它,但是我记得奇数状态值通常表示成功,而偶数值表示失败。C实现映射01return 0;表示成功终止。其他值不变地传递,因此return 1;也表示成功终止。EXIT_FAILURE该值的偶数非零。)


@KeithThompson您能否澄清有关VMS(OpenVMS?)的答案。尚不清楚0和1之间的关系EXIT_SUCCESS / EXIT_FAILURE。我将改为解释奇/偶值。
malat

@malat:您实际上使用过VMS吗?
基思·汤普森

不,从未使用过。我一直在寻找一个规范的答案,因为维基百科使用了不同的措辞
malat

1
@Rhymoid:这是C而不是POSIX指定的。
基思·汤普森

1
@DeanP:0EXIT_SUCCESS不能保证具有相同的值(我在回答中提到),但是它们都表示成功终止。EXIT_SUCCESS从风格上讲,如果您也使用会更好EXIT_FAILURE,但是还可以exit(0)
基思·汤普森

25

不要紧。两者是相同的。

C ++标准语录:

如果status的值为零或EXIT_SUCCESS,则返回实现定义的状态成功终止的形式。


12
这对编译器无关紧要,但可能与样式有关。
celtschk 2012年

2
@celtschk:风格问题是基于感知的,也就是非标准化的,因此不算差异。您只能将Apple与Apple进行比较,而不能将Apple与Pears进行比较。
Alok保存

3
不能保证EXIT_SUCCESS == 0。另一方面,没有充分的理由不这样做。
基思·汤普森

@KeithThompson:为什么不能保证EXIT_SUCCESS == 0。请更清楚地说明。
毁灭者

2
@PravasiMeet:一个系统可能有多个表示成功的值。
基思·汤普森

11

根据定义,0是一个幻数。令人高兴的是,EXIT_SUCCESS几乎普遍等于0。那么,为什么不返回/退出0呢?

退出(EXIT_SUCCESS); 含义很清楚。

退出(0); 另一方面,在某些方面是违反直觉的。不熟悉shell行为的人可能会认为0 == false ==不好,就像C中的其他所有用法0一样。但是不,在这种特殊情况下,0 ==成功==很好。对于大多数经验丰富的开发人员而言,这不会是一个问题。但是,为什么绝对没有理由绊倒新人呢?

tl; dr-如果您的幻数有一个定义的常数,几乎没有理由不使用常数。它更易于搜索,通常更清晰,等等,并且不会花费您任何费用。


我认为您对人们期望0会自动变坏的评论不切实际。即使在stdlib中,也有很多API使用0表示成功,使用非0表示失败。例如STDLIB( fclose()setvbuf(),...),POSIX( ,,listen() ,...),和许多,许多其他的库(例如,OpenGL的[ ],ZLIB [ / / ...],SDL [ / ...],和更多)。pthread_create()pipe()glGetError()deflate()inflate()SDL_CreateWindowAndRenderer()
TimČas17年

2
当然,在其他情况下,“ 0”用于“成功”,但他认为它令人困惑是正确的。
保罗·温兹

10

这是一个永无止境的故事,反映了“互操作性和整体可移植性”的局限性(神话)。

程序应返回什么来指示“成功”,应该由谁接收值(操作系统或调用程序的进程)来定义,而不是由语言规范来定义。

但是程序员喜欢以“便携式”方式编写代码,因此他们为定义返回的符号值的“操作系统”概念发明了自己的模型。

现在,在多对多方案(许多语言用于向许多系统编写程序的情况)中,“成功”的语言约定与操作系统的约定(没有人可以授予总是相同的含义)之间的对应关系由特定目标平台的库的特定实现处理。

但是-不幸的是-这些概念在部署C语言时(主要是编写UNIX内核)时还不清楚,而千兆字节的书说“返回0表示成功”,因为这在OS上是正确的那个时候有一个C编译器。

从那时起,就如何处理这种对应关系一直没有明确的标准化。C和C ++有其自己的“返回值”定义,但没有人提供适当的OS转换(或更优的是:没有编译器文档对此有所说明)。对于UNIX-LINUX和-基于独立原因-对于Windows,如果为true,则表示成功,并且0表示成功,并且它涵盖了90%的现有“消费者计算机”,在大多数情况下-忽略返回值(因此我们可以讨论了几十年,但没人会注意到!)

在这种情况下,在做出决定之前,请问以下问题:-我是否想就我的现有情况向来电者传达一些信息?(如果我总是始终返回0…则所有内容都没有任何线索)-我的呼叫者是否对此通信有约定?(请注意,单个值不是约定:不允许任何信息表示)

如果两个答案都为“否”,则可能好的解决方案是根本不编写主return语句。(并且让编译器决定,相对于目标是否正在工作)。

如果没有约定,则0 =成功满足大多数情况(如果使用符号引入约定,则使用符号可能会出现问题)。

如果有约定,请确保使用与它们一致的符号常量(并确保平台之间的约定一致性而不是值一致性)。


4

一旦您开始编写可以返回无数退出状态的代码,就可以#define对所有这些状态进行操作。在这种情况下EXIT_SUCCESS,在不是“ 魔术数字 ”的情况下有意义。这使您的代码更具可读性,因为其他所有退出代码都将是EXIT_SOMETHING。如果您只是编写一个程序,该程序将在完成后返回,它return 0是有效的,甚至可能更干净,因为它表明没有复杂的返回码结构。


0

从程序返回的只是一个约定。

不,我无法想到“ EXIT_SUCCESS” 不会出现的任何情况为“ 0”。

我个人建议“ 0”。

恕我直言...


1
我从事C ++编程已有10年了,但仍然不记得0代表返回值是成功还是失败。
lahjaton_j

@lahjaton_j我了解。它认为这是因为它具有相反的直观性:0是错误的,并且许多函数0在失败时/不执行任何操作时都会返回。
含义-


-5

一些编译器可能会对此产生问题-在Mac C ++编译器上,EXIT_SUCCESS对我来说运行良好,但在Linux C ++编译器上,我必须为其添加cstdlib才能知道EXIT_SUCCESS是什么。除此之外,它们是相同的。


我的意思是在Mac上EXIT_SUCCESS可以在不包括cstdlib的情况下工作。
2012年

4
如果EXIT_SUCCESS在不包含<stdlib.h>或的情况下工作<cstdlib>,则必须有其他一些头直接或间接定义了它。在C ++中,标准标头到#include其他标准标头很常见。如果编译时没有错误:int main() { return EXIT_SUCCESS; }那么您的编译器可能有错误。
基思·汤普森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.