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

Tre*_*key 107 c c++ program-entry-point return-value

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

#include <cstdlib>
int main(){return EXIT_SUCCESS;}
Run Code Online (Sandbox Code Playgroud)

要么

int main(){return 0;}
Run Code Online (Sandbox Code Playgroud)

它们是完全相同的吗?应该EXIT_SUCCESS只与exit()?一起使用?

我认为EXIT_SUCCESS这是一个更好的选择,因为其他软件可能想要将零视为失败,但我也听说如果你返回0,编译器无论如何都能够将它改为不同的值.

Kei*_*son 134

EXIT_FAILURE,无论是在返回语句中main还是作为参数exit(),都是在C或C++程序中指示失败的唯一可移植方式. exit(1)例如,实际上可以表示在VMS上成功终止.

如果你将EXIT_FAILURE在程序失败时使用,那么你也可以EXIT_SUCCESS在成功时使用,只是为了对称.

另一方面,如果程序从不发出故障信号,您可以使用0EXIT_SUCCESS.两者均由标准保证,表示成功完成.(几乎不可能EXIT_SUCCESS有一个0以外的值,但是在我听过的每个实现上都等于0.)

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

对于这个问题,在C开始与1999年的标准,并在C++的所有版本,达到年底main()执行一个隐含的return 0;,所以你可能不需要为使用0EXIT_SUCCESS明确.(但至少在C中,我认为明确return 0;的是更好的风格.)

(有人询问OpenVMS.我很久没有使用它了,但是我记得奇怪的状态值通常表示成功,而偶数值表示失败.C实现映射01,所以return 0;表示成功终止.其他值传递不变,所以return 1;也表示成功终止.EXIT_FAILURE将具有非零均值.)

  • @Rhymoid:这是由 C 指定的,而不是 POSIX。 (4认同)
  • 这是个人的(出于同样的动机:显式),但我喜欢“return(0)”(或!= 0),因为 shell 脚本“$?” 兼容性(大多数 UNIX 程序返回“$?”=0 表示成功)。 (2认同)
  • @AndréA.G.Scotá:POSIX 保证 `EXIT_SUCCESS==0`。(并且你不需要在“return”语句上使用括号。就我个人而言,我认为它们使它看起来太像函数调用。) (2认同)

Alo*_*ave 24

不要紧.两者都是一样的.

C++标准语录:

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

  • 它与编译器无关,但它可能是一种风格问题. (12认同)
  • 无法保证`EXIT_SUCCESS == 0`.另一方面,没有充分的理由不这样做. (3认同)
  • @celtschk:风格的问题是基于感知而非标准化,因此不能算作差异.你只能将苹果与苹果而不是苹果与梨比较. (2认同)
  • @PravasiMeet:系统可能有多个表示成功的值. (2认同)
  • 功能重于形式,但清晰度重于功能。我可以从专业经验告诉你,风格在编程中非常重要。 (2认同)

Jam*_*mes 10

根据定义,0是幻数.EXIT_SUCCESS几乎普遍等于0,非常高兴.那么为什么不返回/退出0呢?

出口(EXIT_SUCCESS); 意义非常明确.

出口(0); 另一方面,在某些方面是违反直觉的.不熟悉shell行为的人可能会假设0 == false == bad,就像在C中每隔一次使用0一样.但是没有 - 在这一个特殊情况下,0 == success == good.对于大多数经验丰富的开发者来说,不会成为问题.但为什么绝对没有理由绊倒新人呢?

tl; dr - 如果你的幻数有一个定义的常数,那么几乎从来没有理由不首先使用常数.它更易于搜索,通常更清晰等等,它不会让您付出任何代价.

  • 我认为你关于人们期望 0 会自动变坏的评论是不切实际的。很多 API 使用 0 表示成功,使用非 0 表示失败,即使在 stdlib 中也是如此。例如 stdlib (`fclose()`、`setvbuf()`、...)、POSIX (`listen()`、`pthread_create()`、`pipe()`、...) 以及许多,** *许多***其他库(例如 OpenGL [`glGetError()`]、zlib [`deflate()`/`inflate()`/...]、SDL [`SDL_CreateWindowAndRenderer()`/...]、和更多)。 (3认同)
  • 当然,在其他情况下,“ 0”用于“成功”,但他认为它令人困惑是正确的。 (2认同)

Emi*_*lia 9

这是一个永无止境的故事,它反映了"所有人的互操作性和可融合性"的限制(一个神话).

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

但是程序员喜欢以"可移植的方式"编写代码,因此他们发明了自己的"操作系统"概念模型,定义了要返回的符号值.

现在,在多对多场景中(许多语言用于向许多系统编写程序),"成功"语言约定与操作系统之间的对应关系(没有人可以授予总是相同的)应该是由特定目标平台的库的特定实现来处理.

但是 - 不幸的是 - 这些概念在部署C语言时并不那么清楚(主要是编写UNIX内核),以及通过说"返回0意味着成功"编写的Gigagrams书籍,因为在操作系统上这是真实的那个时候有一个C编译器.

从那以后,没有明确标准化如何处理这种通信.C和C++有自己的"返回值"定义,但没有人授予适当的操作系统转换(或更好:没有编译器文档说明任何内容).0表示成功,如果UNIX为真 - LINUX和 - 由于独立原因 - 对于Windows,这涵盖了90%的现有"消费者计算机",在大多数情况下 - 忽略了返回值(所以我们可以讨论几十年,没有人会注意到!)

在这个场景中,在做出决定之前,请问这些问题: - 我是否有兴趣向我的来电者传达有关我现有的信息?(如果我总是返回0 ......所有事情背后都没有任何线索) - 我的来电者是否有关于这种沟通的惯例?(请注意,单个值不是约定:不允许任何信息表示)

如果这两个答案都不是,那么好的解决办法就是不要写主要的return语句.(并让编译器决定,就目标而言正在努力).

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

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