当前位置:  开发笔记 > 编程语言 > 正文

main()中的return语句vs exit()

如何解决《main()中的return语句vsexit()》经验,为你挑选了6个好方法。

我应该使用exit()还是只是return声明main()?我个人赞成这些return陈述,因为我觉得这就像在阅读代码时读取任何其他功能和流量控制一样顺畅(在我看来).即使我想重构main()函数,return看起来似乎是一个更好的选择exit().

做一些exit()不特别的事return吗?



1> FreeMemory..:

其实,有 有差别,但它是微妙的.它对C++有更多的影响,但差异很重要.

当我调用returnmain(),将为我的本地范围对象调用析构函数.如果我调用exit(),将不会为我的本地范围对象调用析构函数!重新阅读.exit() 不回来.这意味着,一旦我称之为"没有后援".您在该函数中创建的任何对象都不会被销毁.通常这没有任何影响,但有时它会像关闭文件一样(当然你希望所有数据都刷新到磁盘?).

请注意,static即使您打电话,也会清理对象exit().最后请注意,如果您使用abort(),则不会销毁任何对象.也就是说,没有全局对象,没有静态对象,也没有本地对象会调用它们的析构函数.

在支持退出退货时谨慎行事.

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a


注意:语句:**不会为我的本地作用域对象调用析构函数!**对于C++ 11不再适用: - 与具有线程存储持续时间的当前线程关联的对象被销毁(仅限C++ 11) .http://www.cplusplus.com/reference/cstdlib/exit/
@Mike:C库文件缓冲区和C++文件流对象之间存在差异.exit() - 作为C库的一部分 - 被设计为与前者协调并刷新,但可以绕过后者:甚至标准C++ fstream内容也不会刷新到磁盘(尝试它 - 我做了,它失败了/ Linux/GCC),显然用户定义的具有缓冲I/O的类型也不会被刷新.
这意味着,将调用`thread_local`对象'析构函数.仍未调用其他本地对象的析构函数.http://ideone.com/Y6Dh3f
顺便说一句,只是要很迂腐,因为这个答案仍可能会造成混淆的用C读者:对于C有关`退出问题()`干净关闭文件其实是错误的.数据可能无法刷新的唯一时间是相反的情况:即,如果一个人使用`main()`中的`return`,一个人调用`setbuf()`或`setvbuf()`,并将缓冲区声明为自动存储`main()`(如下面R.的答案所述).这个问题用C和C++标记(而且编码风格 - 这不是样式问题!)真是太糟糕了.

2> jwfearn..:

另一个区别 exit是:标准库函数,因此您需要包含标题并与标准库链接.为了说明(在C++中),这是一个有效的程序:

int main() { return 0; }

但要使用exit你需要一个包括:

#include 
int main() { exit(EXIT_SUCCESS); }

另外,这增加了一个额外的假设:调用exit来自main返回零具有相同的副作用.正如其他人所指出的,这取决于你正在构建什么样的可执行文件(即谁在调用main).您在编写使用C运行时的应用程序吗?Maya插件?一个Windows服务?一个司机?每个案例都需要研究,看看是否exit相当于return.恕我直言,exit当你真正的意思 return是让代码更混乱.OTOH,如果你真的 有意思,那么一定exit要用它.



3> R....:

至少有一个理由需要exit:如果您的任何atexit处理程序引用自动存储持续时间数据main,或者您使用setvbufsetbuf分配给其中一个标准流,则自动存储持续时间缓冲区main,然后从main产生返回未定义的行为,但调用exit有效.

另一个潜在的用法(通常保留给玩具程序)是从具有递归调用的程序退出main.


@Seb:您似乎相信通过解释标准的自然语言文本可以理解C语言,就好像它是完全严格的一样.这根本不可能.规范包含错误,当一个简单的脚注澄清他们已经知道他们犯了错误但读者可以理解它时,WG14不会浪费时间重写内容.
@Seb:意图显然不是要覆盖对自动存储行为的要求,而且脚注显然是为了澄清这一点.是的,C标准中有不精确的措词.任何读过它的人都知道这一点.我们也知道委员会通常不会解决这样的问题,因为意图已经很明显了.

4> Alnitak..:

我总是使用,return因为标准原型main()说它确实返回了int.

也就是说,标准的某些版本给出了main特殊处理,并假设如果没有明确的return声明则返回0 .给出以下代码:

int foo() {}
int main(int argc, char *argv[]) {}

G ++仅为以下内容生成警告foo()并忽略丢失的返回main:

% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function


如果没有return语句,C99和C++返回0,而C90没有.

5> Greg A. Wood..:

强烈支持 R.关于使用exit()的评论,以避免main()在程序实际结束之前回收自动存储。return X;in中的语句main()并不完全等同于对的调用exit(X);,因为返回main()时动态存储消失了main(),但是如果exit()改为调用,它就不会消失。

此外,在C或任何类似C的语言中,一条return语句强烈地向读者暗示执行将在调用函数中继续,并且从技术上讲,这种连续执行通常是正确的,如果您算上调用了main()函数的C启动例程,则不是到底是什么,你的意思是,当你的意思是结束该进程。

毕竟,如果你想从任何其它函数中结束你的程序,除了main()必须调用exit()。一致地执行此操作main()还可以使您的代码更具可读性,并且任何人都可以更轻松地重构您的代码。即从复制的代码main(),因为偶然的一些其他功能不会胡作非为return,发言exit()调用。

因此,将所有这些点结合在一起,得出的结论是,至少对于C语言来说,使用语句在中结束程序是一种不良习惯returnmain()



6> Adrian McCar..:

exit()会执行“返回”没有的特殊功能吗?

对于某些不常见平台的编译器,exit()可能会将其参数转换为程序的退出值,而从的返回main()可能只是将值直接传递给主机环境,而无需任何转换。

在这些情况下,该标准要求具有相同的行为(特别是,它说返回与- int兼容的内容main()应该等同于exit()使用该值进行调用)。问题在于,不同的操作系统具有不同的解释出口值的约定。在许多(MANY!)系统上,0表示成功,其他则表示失败。但是在VMS上,奇数表示成功,偶数表示失败。如果从返回0 main(),则VMS用户将看到有关访问冲突的令人讨厌的消息。实际上并没有访问冲突-仅仅是与故障代码0相关的标准消息。

然后ANSI出现并得到祝福EXIT_SUCCESSEXIT_FAILURE作为参数可以传递给ANSI exit()。该标准还说exit(0)应该表现得与之相同exit(EXIT_SUCCESS),因此大多数实现都将其定义EXIT_SUCCESS0

因此,该标准使您陷入VMS的困境,因为它没有标准的方法可以返回恰好具有值0 的失败代码。

因此,1990年代初期的VAX / VMS C编译器没有解释的返回值main(),它只是将任何值返回给主机环境。但是,如果使用exit()它,它将满足标准要求:将EXIT_SUCCESS(或0)转换为成功代码和EXIT_FAILURE通用失败代码。要使用它EXIT_SUCCESS,您必须将其传递给exit(),您不能从中将其返回main()。我不知道该编译器的更现代版本是否保留了该行为。

一个可移植的C程序,看起来像这样:

#include 
#include 

int main() {
  printf("Hello, World!\n");
  exit(EXIT_SUCCESS);  /* to get good return value to OS */
  /*NOTREACHED*/ /* to silence lint warning */
  return 0;  /* to silence compiler warning */
}

顺便说一句:如果我没记错的话,退出值的VMS约定比奇/偶更细微。实际上,它使用诸如低三位之类的代码来对严重性级别进行编码。但是,一般而言,奇数严重性级别表示成功或其他信息,偶数严重性级别表示错误。

推荐阅读
jerry613
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有