我应该在 main()
中使用 exit()
还是只使用 return
语句?就我个人而言,我更喜欢 return
语句,因为我觉得它就像阅读任何其他函数一样,并且当我阅读代码时流程控制很流畅(在我看来)。即使我想重构 main()
函数,使用 return
似乎比 exit()
更好。
exit()
有没有做任何 return
没有做的特殊事情?
其实还是有区别的,但是很微妙。它对 C++ 有更多的影响,但差异很重要。
当我在 main()
中调用 return
时,将为我的本地范围对象调用析构函数。如果我调用 exit()
,将不会为我的本地范围对象调用任何析构函数!重新阅读。 exit()
不返回。这意味着,一旦我称它为,就“没有后盾”。您在该函数中创建的任何对象都不会被销毁。通常这没有任何影响,但有时确实如此,例如关闭文件(您肯定希望所有数据都刷新到磁盘吗?)。
请注意,即使您调用 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
具有与返回零相同的副作用。正如其他人指出的那样,这取决于您正在构建的可执行文件类型(即,谁在调用 main
)。您是否正在编写使用 C 运行时的应用程序?玛雅插件? Windows 服务?一个司机?每个案例都需要研究以确定 exit
是否等同于 return
。恕我直言,当您真正的意思时使用 exit
return
只会使代码更加混乱。 OTOH,如果您真的是说 exit
,那么一定要使用它。
exit()
。 Return vs Exit from main function in C 有一些引用标准的答案。如果您的程序未作为独立进程运行,则第一个函数可能不称为 main
。如果是的话,你正在做一些奇怪的巫术,而不是在 ISO C 领域了。
首选 exit
的原因至少有一个:如果您的任何 atexit
处理程序引用 main
中的自动存储持续时间数据,或者如果您使用 setvbuf
或 setbuf
分配给标准在 main
中流式传输自动存储持续时间缓冲区,然后从 main
返回会产生未定义的行为,但调用 exit
是有效的。
另一种可能的用法(通常保留给玩具程序)是从递归调用 main
的程序中退出。
main()
没有什么特别之处——它只是一个和其他函数一样的函数。另一方面,由于它在标准中特别提到,标准必须非常小心地定义它如何定义 main()
以及它附近和亲爱的东西。然而最终,尽管标准没有(并且不得)要求编译器对 main()
中的自动存储做任何特别的事情。请注意阅读您在评论中引用的段落下方的Footnote #11。
我总是使用 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()
也是一种有效的、有时是必要的方式来结束任何函数的执行。事实上,正如我和其他人在其他地方所描述的那样,即使从 main()
调用 exit()
也表达了退出整个进程的更明确的意图,保留自动存储直到进程退出,并且在将来的代码重构期间更容易维护。对于 C 在 main()
中使用 return
的意图是结束进程时,因此可以说是一种不好的做法。
exit()
而不是在 main 中使用 return
的情况。另一方面,我在包装对 main()
的调用时遇到了问题,该调用不必要地使用了 exit()
。这里的绝大多数答案和评论似乎不同意您的断言,即在 main()
中使用 return
是“一种不好的做法”。
我强烈支持 R. 关于使用 exit() 的评论,以避免在程序实际结束之前回收 main()
中的自动存储。 main()
中的 return X;
语句并不完全等同于对 exit(X);
的调用,因为 main()
的动态存储在 main()
返回时会消失,但如果对 exit()
的调用是取而代之。
此外,在 C 或任何类似 C 的语言中,return
语句强烈暗示读者将在调用函数中继续执行,虽然如果计算调用 { 2} 函数,当你打算结束进程时,这并不是 你 的意思。
毕竟,如果您想从除 main()
之外的任何其他函数中结束程序,您必须调用 exit()
。在 main()
中始终如一地这样做也会使您的代码更具可读性,并且还使任何人都可以更轻松地重构您的代码;即,从 main()
复制到其他函数的代码不会因为意外的 return
语句应该被 exit()
调用而出现异常。
因此,将所有这些观点结合在一起,得出的结论是,至少对于 C 来说,使用 return
语句在 main()
中结束程序是一个坏习惯。
exit()
,但如果 throw
或 abort()
替代方案在特定上下文中不起作用,请使用它。但尤其要避免在 main 中使用 exit()
,并在 main 中使用 return 作为典型做法。
exit() 会做任何“return”没有做的特殊事情吗?
对于一些用于不常见平台的编译器,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 的故障代码。
因此,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 约定比奇数/偶数更细微。它实际上使用像低三位这样的东西来编码严重性级别。然而,一般来说,奇数严重级别表示成功或杂项信息,偶数严重级别表示错误。
main
的值 returned
与传递给 exit
的值不同 - 但标准明确指出,“如果 main
的返回类型 b>函数是与int
兼容的类型,从初始调用返回main
函数相当于调用exit
< /b> 函数,将 main
函数的返回值作为其参数”。那是C11; C89/C90 的措辞几乎相同。
EXIT_SUCCESS
相同的处理方式,因此无法返回值为 0 的特定于平台的 failure 状态,这可能是某些那个时代的编译器对 return-from-main 和 exit()
的处理方式不同。
在 C 中,从 main
返回与使用相同值调用 exit
完全相同。
C standard 的第 5.1.2.2.3 节规定:
如果 main 函数的返回类型是与 int 兼容的类型,则从初始调用到 main 函数的 return 等效于以 main 函数返回的值作为参数调用 exit 函数; 11)到达终止main函数的}返回值0。如果返回类型与int不兼容,则返回给宿主环境的终止状态是未指定的。
正如其他答案中提到的,C++ 的规则有点不同。
main
中的 exit(0)
和 return(0)
实际上是有区别的——当您的 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。
不定期副业成功案例分享
thread_local
个对象的析构函数。其他本地对象的析构函数仍然没有被调用。 ideone.com/Y6Dh3fexit()
干净地关闭文件的问题实际上是错误的。唯一可能不刷新数据的情况是在相反的情况下:即,如果一个使用来自main()
的return
,并且一个调用setbuf()
或setvbuf()
并在main()
中声明为自动存储(如所讨论的)在下面 R. 的回答中)。真是太糟糕了,这个问题同时被 C 和 C++ 标记(以及编码风格——这不是风格问题!)。