我应该在exit()
中使用return
还是main()
语句?我个人赞成return
语句,因为我觉得在阅读代码时,阅读任何其他函数和流控制都很顺利(在我看来)。即使我想重构main()
函数,return
似乎是比exit()
更好的选择。
exit()
执行return
没有做什么特别的事情吗?
答案 0 :(得分:264)
实际上, 是一个区别,但它很微妙。它对C ++有更多的影响,但差异很重要。
当我在return
中调用main()
时,将为我的本地作用域对象调用析构函数。如果我调用exit()
,将不会为我的本地作用域对象调用析构函数!重新读取它。 exit()
未返回。这意味着,一旦我称之为“没有后援”。您在该函数中创建的任何对象都不会被销毁。通常这没有任何影响,但有时会这样做,比如关闭文件(当然你希望所有数据都刷新到磁盘?)。
请注意,即使您拨打static
,也会清除exit()
个对象。最后请注意,如果使用abort()
,则不会销毁任何对象。也就是说,没有全局对象,没有静态对象,也没有本地对象会调用它们的析构函数。
在支持退出而不是返回时请谨慎行事。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
答案 1 :(得分:23)
另一个区别:
exit
是标准库
功能,所以你需要包括
标题和标准链接
图书馆。为了说明(在C ++中),
这是一个有效的计划:
int main() { return 0; }
但要使用exit
,您需要一个包含:
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }
另外,这增加了一个额外的假设:从exit
调用main
与返回零具有相同的副作用。正如其他人所指出的,这取决于您正在构建的可执行文件类型(即,谁正在调用main
)。您在编写使用C运行时的应用程序吗? Maya插件?一个Windows服务?一个司机?每个案例都需要进行研究,以确定exit
是否等同于return
。当你真正意味着 exit
时,恕我直言使用return
只会让代码更加混乱。 OTOH,如果你真的意味着 exit
,那么一定要使用它。
答案 2 :(得分:15)
至少有一个理由更喜欢exit
:如果您的atexit
处理程序中的任何一个在main
中引用了自动存储持续时间数据,或者您使用了setvbuf
或setbuf
在main
中为其中一个标准流分配自动存储持续时间缓冲区,然后从main
返回产生未定义的行为,但调用exit
有效
另一个潜在用法(通常为玩具程序保留)是从main
的递归调用退出程序。
答案 3 :(得分:5)
我总是使用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
答案 4 :(得分:5)
我强烈第二条R.关于使用exit()的评论,以避免在程序实际结束之前回收main()
中的自动存储。 return X;
中的main()
语句与exit(X);
的调用不完全相同,因为main()
的动态存储在main()
返回时消失,但它会如果改为调用exit()
,则不会消失。
此外,在C或任何类C语言中,return
语句强烈暗示读者将在调用函数中继续执行,而如果计算C启动,这种继续执行通常在技术上是正确的例如,你的main()
函数被调用,当你想要结束这个过程时,它并不是你的意思。
毕竟,如果您想从main()
以外的任何其他功能中结束您的程序,必须致电exit()
。在main()
中持续这样做也会使您的代码更具可读性,并且它还使任何人都可以更轻松地重新编写代码。即,从main()
复制到某个其他函数的代码不会因为 应该return
调用的exit()
语句错误行为。
因此,将所有这些要点结合在一起得出结论是,至少对于C来说,使用return
语句来结束{{1}中的程序是坏习惯 }。
答案 5 :(得分:5)
exit()是否会执行'return'不具备的特殊功能?
对于一些非常见平台的编译器,exit()
可能会将其参数转换为程序的退出值,而main()
的返回可能只是将值直接传递给主机环境而不进行任何转换。
标准要求在这些情况下具有相同的行为(具体而言,它表示返回int
- 与main()
兼容的内容应该等同于使用该值调用exit()
。问题是不同的操作系统有不同的惯例来解释退出值。在许多(MANY!)系统上,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约定比奇数/偶数更细微。它实际上使用类似低三位的内容来编码严重性级别。但是,一般来说,奇怪的严重程度表示成功或杂项信息,偶数表示错误。
答案 6 :(得分:0)
在C语言中,从main
返回的操作与调用具有相同值的exit
完全相同。
C standard的第5.1.2.2.3节:
如果主函数的返回类型是与int兼容的类型 ,从初始调用到主函数的返回等同于 用main返回的值调用exit函数 作为其参数; 11)到达},以终止 main函数返回的值为0。如果返回类型为 与int不兼容,终止状态返回到 主机环境未指定。
C ++的规则与其他答案中提到的有些不同。
答案 7 :(得分:0)
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。