Answers:
其实,有是 有差别,但它是微妙的。它对C ++具有更多含义,但是区别很重要。
当我调用return
时main()
,将为本地作用域的对象调用析构函数。如果我调用exit()
,则不会为本地作用域的对象调用析构函数!重新阅读。exit()
不返回。这意味着一旦我调用它,就不会有“后援”。您在该函数中创建的所有对象都不会被破坏。通常,这没有任何意义,但有时却可以,例如关闭文件(确定要将所有数据刷新到磁盘吗?)。
请注意,static
即使您调用,对象也会被清理exit()
。最后请注意,如果使用abort()
,则不会破坏任何对象。也就是说,不会调用全局对象,静态对象和本地对象的析构函数。
当倾向于退出而不是收益时,请谨慎行事。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
thread_local
将调用对象的析构函数。其他本地对象的析构函数仍未调用。ideone.com/Y6Dh3f
exit()
干净关闭文件的问题实际上是错误的。唯一可能不刷新数据的情况是相反的情况:即,如果一个用户使用return
from main()
并且一个已调用setbuf()
或setvbuf()
使用一个声明为自动存储在其中的缓冲区main()
(如下面R.的答案所述)。这个问题同时用C和C ++标记(以及编码样式,这不是样式问题!),真是太糟糕了。
另一个区别:
exit
是标准库函数,因此您需要包括标头并与标准库链接。为了说明(在C ++中),这是一个有效的程序:
int main() { return 0; }
但是要使用,exit
您需要包含:
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }
此外,这还增加了一个附加假设:exit
from main
的调用与返回零具有相同的副作用。正如其他人指出的那样,这取决于您正在构建哪种可执行文件(即谁在调用main
)。您是否正在编写使用C运行时的应用程序?Maya插件?Windows服务?一个司机?每个案例都需要进行研究,看是否exit
等同于return
。恕我直言exit
,您的意思 return
是使代码更加混乱。OTOH,如果您确实是故意的 exit
,那么请务必使用它。
至少有一个理由要使用exit
:如果您的任何atexit
处理程序在中引用了自动存储持续时间数据main
,或者您使用setvbuf
或setbuf
将的自动存储持续时间缓冲区分配给其中一个标准流main
,则从main
Produces 返回未定义的行为,但调用exit
有效。
另一个潜在的用法(但是通常保留给玩具程序使用)是从递归调用退出程序main
。
我经常使用,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
来结束其执行。调用exit()
也是结束任何函数执行的有效且有时是必要的方式。确实,正如我和其他人在其他地方所描述的那样,exit()
即使从调用也main()
传达了退出整个流程的明确意图,保留自动存储直到流程退出,并在将来的代码重构中简化维护。因此,对于C而言return
,main()
在意图将要结束时使用in 是一种不好的做法。
我强烈支持 R.关于使用exit()的评论,以避免main()
在程序实际结束之前回收自动存储。return X;
in中的语句main()
并不完全等同于对的调用exit(X);
,因为动态存储main()
在main()
返回时消失,但如果exit()
改为调用,它就不会消失。
此外,在C或任何类似C的语言中,一条return
语句强烈地向读者暗示执行将继续在调用函数中进行,而从技术上讲,这种连续执行通常是正确的,如果您算上调用了main()
函数的C启动例程,则不是到底是什么,你的意思是,当你的意思是结束该进程。
毕竟,如果要从除main()
您之外的任何其他函数中结束程序必须调用exit()
。一致地执行此操作main()
还可以使您的代码更具可读性,并且任何人都可以更轻松地重构您的代码。即从复制的代码main()
,因为偶然的一些其他功能不会胡作非为return
,发言应被exit()
调用。
因此,将所有这些观点结合在一起,得出的结论是,这是一个坏习惯至少对于C语言来说,使用return
语句在中结束程序main()
。
exit()
一般避免使用,但如果a throw
或abort()
替代方法在特定情况下不起作用,请使用它。但是特别要避免exit()
以main为主要做法,而改为以main为回报。
exit()会执行“返回”所没有的特殊功能吗?
对于某些针对不常见平台的编译器,exit()
可能会在执行以下操作的同时将其参数转换为程序的退出值:main()
可能会将其值直接传递给主机环境,而不进行任何转换。
在这些情况下,该标准要求具有相同的行为(特别是,它说返回int
兼容的东西main()
应该等同于exit()
使用该值进行调用)。问题在于,不同的操作系统具有不同的解释出口值的约定。在许多(MANY!)系统上,0表示成功,其他则表示失败。但是在VMS上,奇数表示成功,偶数表示失败。如果从返回0 main()
,则VMS用户将看到有关访问冲突的令人讨厌的消息。实际上并没有访问冲突-仅仅是与故障代码0相关的标准消息。
然后ANSI出现并得到祝福EXIT_SUCCESS
,EXIT_FAILURE
作为参数可以传递给ANSI exit()
。该标准还说exit(0)
应该表现得与之相同exit(EXIT_SUCCESS)
,因此大多数实现都将其定义EXIT_SUCCESS
为0
。
因此,该标准使您陷入VMS的困境,因为它没有标准的方法可以返回恰好值为0 的故障代码。
因此,1990年代初期的VAX / VMS C编译器没有解释来自 main()
,它只是将任何值返回给主机环境。但是,如果使用exit()
它,它将满足标准要求:将EXIT_SUCCESS
(或0
)转换为成功代码和EXIT_FAILURE
通用失败代码。要使用它EXIT_SUCCESS
,您必须将其传递给exit()
,但不能从退还main()
。我不知道该编译器的更现代版本是否保留了该行为。
一个可移植的C程序,看起来像这样:
#include <stdio.h>
#include <stdlib.h>
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约定比奇/偶更细微。实际上,它使用诸如低三位之类的东西来对严重性级别进行编码。但是,一般而言,奇数严重级别表示成功或其他信息,偶数严重级别表示错误。
returned
的方法main
不同exit
-但标准特别指出:“如果main
函数的返回类型与兼容int
,则从初始调用到main
函数的返回为等效于以exit
函数返回的值main
作为参数来调用函数”。那是C11;C89 / C90的措词几乎相同。
EXIT_SUCCESS
,因此无法返回值为0 的特定于平台的故障状态,这可能就是为什么该时代的某些编译器将return-from-main视为和exit()
不同的。
实际上存在的差异exit(0)
,并return(0)
在main
-当你的main
函数被调用多次。
以下程序
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
return(0);
printf("%d", main(argc - 1, argv));
}
运行为
./program 0 0 0 0
将导致以下输出:
00000
但是这个:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
exit(0);
printf("%d", main(argc - 1, argv));
}
无论参数如何,都不会打印任何内容。
如果您确定没有人会main
显式地调用您的代码,那么从技术上来说,这通常不会有太大的区别,但是维护更清晰的代码exit
会更好。如果出于某些原因想要打电话main
–您应根据需要进行调整。
谈到C。