216

我应该使用exit()还是只使用return语句main()?就我个人而言,我喜欢这些return陈述,因为我觉得它就像阅读任何其他函数一样,并且当我阅读代码时流程控制很流畅(在我看来)。即使我想重构main()函数,拥有return似乎比exit().

做一些没有exit()做的特别的事情return吗?

4

8 回答 8

298

其实还是 有区别的,但是很微妙。它对 C++ 有更多的影响,但差异很重要。

当我调用returnmain(),将为我的本地范围对象调用析构函数。如果我调用exit()则不会为我的本地范围对象调用析构函数!再读一遍。exit() 不返回。这意味着,一旦我称它为,就“没有后盾”。您在该函数中创建的任何对象都不会被销毁。通常这没有任何影响,但有时确实如此,例如关闭文件(您肯定希望所有数据都刷新到磁盘吗?)。

请注意,static即使您调用exit(). 最后请注意,如果您使用abort(),则不会销毁任何对象。也就是说,不会调用全局对象、静态对象和局部对象的析构函数。

在倾向于退出而不是返回时要谨慎行事。

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a

于 2009-01-20T14:30:54.290 回答
27

另一个区别: exit是标准库函数,因此您需要包含标头并与标准库链接。为了说明(在 C++ 中),这是一个有效的程序:

int main() { return 0; }

但要使用exit你需要一个包括:

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

另外,这增加了一个额外的假设:调用exitfrommain与返回零具有相同的副作用。正如其他人指出的那样,这取决于您正在构建什么样的可执行文件(即,谁在调用main)。您是否正在编写使用 C 运行时的应用程序?玛雅插件?Windows 服务?一个司机?每个案例都需要研究,看看是否exit等同于return. 恕我直言,exit当您真正的意思 return时使用只会使代码更加混乱。OTOH,如果你真的是意思 exit,那么一定要使用它。

于 2009-01-20T15:50:02.400 回答
18

至少有一个理由更喜欢exit:如果您的任何处理atexit程序在未定义的行为,但调用是有效的。mainsetvbufsetbufmainmainexit

另一个潜在用途(通常保留给玩具程序)是从具有递归调用的程序中退出main.

于 2011-05-02T12:07:32.970 回答
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
于 2009-01-20T14:17:48.780 回答
5

强烈支持 R. 关于使用 exit() 的评论,以避免在main()程序实际结束之前回收自动存储。in的return X;语句main()并不完全等同于对 的调用exit(X);,因为动态存储在返回main()时会消失main(),但如果改为调用,它不会消失exit()

此外,在 C 或任何类似 C 的语言中,一条return语句强烈暗示读者将在调用函数中继续执行,虽然如果计算调用main()函数的 C 启动例程,这种继续执行通常在技术上是正确的,但事实并非如此当您打算结束该过程时,这正是的意思。

毕竟,如果你想从任何其他函数中结束你的程序,除了main()必须调用exit(). 始终如一地这样做main()也会使您的代码更具可读性,并且还使任何人都可以更轻松地重构您的代码;main()即,从其他函数复制的代码不会因为本调用的意外return语句而行为不端。exit()

因此,将所有这些点结合在一起,得出的结论是,至少对于 C 来说,使用语句结束程序是一个坏习惯returnmain()

于 2011-06-26T21:29:57.463 回答
5

exit() 会做任何“return”没有做的特殊事情吗?

对于不常见平台的一些编译器,exit()可能会将其参数转换为程序的退出值,而 return frommain()可能只是将值直接传递给主机环境而无需任何转换。

在这些情况下,该标准需要相同的行为(具体来说,它表示返回与int- 兼容的内容main()应该等同于exit()使用该值进行调用)。问题是不同的操作系统有不同的解释退出值的约定。在许多(很多!)系统上,0 意味着成功,其他任何东西都是失败。但是在 VMS 上,奇数表示成功,偶数表示失败。如果您从 中返回 0 main(),则 VMS 用户会看到一条关于访问冲突的令人讨厌的消息。实际上并没有访问冲突——这只是与失败代码 0 相关的标准消息。

然后 ANSI 出现并得到祝福EXIT_SUCCESS,并且EXIT_FAILURE可以作为参数传递给exit(). 该标准还说exit(0)应该与 的行为相同exit(EXIT_SUCCESS),因此大多数实现都定义EXIT_SUCCESS0

因此,该标准将您置于 VMS 的约束中,因为它没有留下任何标准方法来返回恰好具有值 0的故障代码。

因此,1990 年代早期的 VAX/VMS C 编译器没有解释 from 的返回值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 约定比奇数/偶数更细微。它实际上使用像低三位这样的东西来编码严重性级别。然而,一般来说,奇数严重级别表示成功或杂项信息,偶数严重级别表示错误。

于 2014-12-04T18:46:59.040 回答
0

在 C 中,从返回与使用相同的值main调用exit完全相同。

C 标准的第 5.1.2.2.3 节规定:

如果 main 函数的返回类型是与 int 兼容的类型,则从初始调用到 main 函数的 return 等效于以 main 函数返回的值作为参数调用 exit 函数;11)到达终止main函数的}返回值0。如果返回类型与int不兼容,则返回给宿主环境的终止状态是未指定的。

正如其他答案中提到的,C++ 的规则有点不同。

于 2019-05-21T14:14:45.073 回答
-1

当你的函数被多次调用时exit(0),实际上是有区别return(0)的。mainmain

以下程序

#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。

于 2019-05-23T13:35:12.733 回答