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

时间:2009-01-20 14:15:11

标签: c++ c coding-style return exit

我应该在exit()中使用return还是main()语句?我个人赞成return语句,因为我觉得在阅读代码时,阅读任何其他函数和流控制都很顺利(在我看来)。即使我想重构main()函数,return似乎是比exit()更好的选择。

exit()执行return没有做什么特别的事情吗?

8 个答案:

答案 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中引用了自动存储持续时间数据,或者您使用了setvbufsetbufmain中为其中一个标准流分配自动存储持续时间缓冲区,然后从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_SUCCESSEXIT_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。