返回语句与退出()在main()
我应该使用exit()
还是仅在main()
return
语句? 就我个人而言,我喜欢return
语句,因为我感觉它就像阅读任何其他函数一样,当我阅读代码时,stream程控制是平滑的(在我看来)。 即使我想重构main()
函数, return
似乎是比exit()
更好的select。
exit()
做了什么特别的return
不?
其实有一个区别,但是很微妙。 它对C ++有更多的含义,但是区别很重要。
当我在main()
调用return
,析构函数会被我的本地作用域对象调用。 如果我调用exit()
, 将不会为我的本地作用域对象调用析构函数! 重新阅读。 exit()
不返回 。 这意味着一旦我称之为“没有后卫”。 您在该函数中创build的任何对象都不会被销毁。 通常这没有任何影响,但有时候它确实如closures文件(当然,你希望所有的数据都被刷新到磁盘上)。
请注意,即使调用exit()
也会清除static
对象。 最后要注意的是,如果使用abort()
,则不会销毁任何对象。 也就是说,没有全局对象,没有静态对象,也没有本地对象会调用析构函数。
谨慎行事时,谨慎退出退出。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
另一个区别是: exit
是一个标准库函数,所以你需要包含标题和链接到标准库。 为了说明(用C ++),这是一个有效的程序:
int main() { return 0; }
但要使用exit
您需要一个包括:
#include <stdlib.h> int main() { exit(EXIT_SUCCESS); }
另外,这增加了一个额外的假设:从main
调用exit
有和返回零相同的副作用。 正如其他人已经指出的,这取决于你正在build立什么样的可执行文件(即谁打电话给main
)。 你正在编写一个使用C运行时的应用程序吗? 玛雅插件? Windows服务? 一个司机? 每个案件将需要研究,看看exit
是否相当于return
。 恕我直言,使用exit
时,你真的意味着 return
只是使代码更混乱。 OTOH,如果你真的意味着 exit
,那么一定要用它。
至less有一个理由更喜欢exit
:如果你的任何一个atexit
处理程序在main
引用了自动存储持续时间数据,或者你使用了setvbuf
或setbuf
来为其中一个标准stream分配一个自动存储持续时间缓冲区main
,然后从main
返回产生未定义的行为,但是调用exit
是有效的。
然而,另一个潜在的用法(通常是为玩具程序保留)是通过recursion调用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
为了避免在程序实际结束之前回收main()
中的自动存储,我强烈地使用了exit()的第二条注释。 return X;
main()
语句并不完全等同于exit(X);
的调用exit(X);
,因为main()
的dynamic存储在main()
返回时消失了,但是如果调用exit()
话,它不会消失。
此外,在C语言或任何类C语言中, return
语句强烈暗示读者执行将继续执行在调用函数中,而如果您计算C调用main()
的C启动例程,function,这不完全是你的意思是结束这个过程。
毕竟,如果你想从main()
以外的任何其他函数中结束你的程序,你必须调用exit()
。 在main()
一直这样做,使得你的代码更具可读性,而且任何人都可以更容易地重新分解你的代码。 即从main()
复制到其他函数的代码将不会因为意外的return
语句而导致错误,这些语句应该是exit()
调用。
所以,把所有这些点结合在一起的结论是,至less对于C来说,使用return
语句来结束main()
的程序是一个坏习惯 。
exit()做了什么特别的“返回”不?
使用一些编译器为非常见的平台, exit()
可能会将其参数转换为程序的退出值,而从main()
返回的值可能只是直接将值传递给主机环境而不进行任何翻译。
标准要求在这些情况下具有相同的行为(具体来说,它表示返回与main()
int
兼容的东西应该相当于使用该值调用exit()
)。 问题是不同的操作系统有不同的约定来解释退出值。 在许多(很多!)系统中,0意味着成功,其他任何事情都是失败的。 但是,就VMS而言,奇数值意味着成功,甚至意味着失败。 如果您从main()
返回0,则VMS用户将看到有关访问冲突的令人讨厌的消息。 实际上没有访问冲突 – 这只是与失败代码0关联的标准消息。
然后ANSI来了,祝福EXIT_SUCCESS
和EXIT_FAILURE
作为你可以传递给exit()
。 该标准还指出exit(0)
应该与exit(EXIT_SUCCESS)
行为相同,所以大多数实现都将EXIT_SUCCESS
定义为0
。
因此,这个标准把你放在VMS上,因为它没有标准的方法来返回碰巧值为0的失败代码。
20世纪90年代早期的时代,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公约的退出值比奇数/偶数更细微。 它实际上使用低三位来编码严重级别。 然而,一般来说,单数的严重程度表示成功或其他信息,偶数表示错误。