在main()中使用exit()或仅使用return语句之间有区别吗?就我个人而言,我更喜欢return语句,因为我觉得它就像阅读任何其他函数一样,而且当我阅读代码时,流控制是流畅的(在我看来)。即使我想重构main()函数,使用return似乎比exit()更好。exit()能做return不能做的事情吗?
main()
exit()
return
wlzqhblo1#
事实上,这是有区别的,但很微妙。它对C++有更多的影响,但差异很重要。当我在main()中调用return时,将为我的局部作用域对象调用析构函数。如果我调用exit(),**不会为我的局部作用域对象调用析构函数!”重读它。exit()不返回。这意味着,一旦我调用它,就没有“回退”,在该函数中创建的任何对象都不会被销毁。这通常没有什么影响,但有时会有影响,比如关闭文件(您肯定希望所有数据都刷新到磁盘?).请注意,即使您调用exit(),static对象也会被清理。最后请注意,如果使用abort(),则不会销毁任何对象。也就是说,没有全局对象,没有静态对象,也没有局部对象会被调用它们的析构函数。
static
abort()
在选择退出而非返回时,请谨慎操作。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
8ftvxx2r2#
另一个区别:exit是一个标准库函数,因此您需要包含标头并链接到标准库。为了说明(在C++中),这是一个有效的程序:
exit
int main() { return 0; }
但是要使用exit,你需要一个include:
#include <stdlib.h> int main() { exit(EXIT_SUCCESS); }
这就增加了一个额外的假设:从main调用exit具有与返回零相同的副作用。正如其他人所指出的,这取决于您正在构建哪种可执行文件(即,谁在调用main)。您是否正在编写一个使用C运行时的应用程序?Maya插件?Windows服务?驱动程序?每个案例都需要研究exit是否等效于return。IMHO使用exit时,你 * 真正的意思是 * return只会使代码更加混乱。OTOH,如果你真的是指exit,那就用它吧。
main
kmynzznz3#
至少有一个理由让我们更喜欢exit:如果您的任何atexit处理程序引用main中的自动存储持续时间数据,或者如果您使用setvbuf或setbuf将main中的自动存储持续时间缓冲区分配给一个标准流,则从main返回将产生未定义的行为,但调用exit是有效的。另一种可能的用法(通常只用于玩具程序)是通过递归调用main退出程序。
atexit
setvbuf
setbuf
13z8s7eq4#
我总是使用return,因为main()的标准原型说它确实返回int。也就是说,某些版本的标准给予main特殊处理,并假设如果没有显式的return语句,则返回0。给定以下代码:
int
int foo() {} int main(int argc, char *argv[]) {}
G++只为foo()生成一个警告,而忽略了main缺少的返回:
foo()
% g++ -Wall -c foo.cc foo.cc: In function ‘int foo()’: foo.cc:1: warning: control reaches end of non-void function
2ul0zpep5#
我强烈第二次评论R。关于使用exit()以避免在程序实际结束之前回收main()中的自动存储。main()中的return X;语句并不完全等同于对exit(X);的调用,因为main()的动态存储在main()返回时消失,但如果调用exit(),它不会消失。此外,在C或任何类似C的语言中,return语句强烈地暗示读者执行将在调用函数中继续,虽然这种执行的继续在技术上通常是正确的,如果你把调用main()函数的C启动例程计算在内,当你打算结束这个过程时,它并不完全是你的意思。毕竟,如果你想在除了main()之外的任何其他函数中结束你的程序,你 * 必须 * 调用exit()。在main()中这样做也会使代码更具可读性,而且任何人都可以更容易地重构代码;也就是说,从main()复制到其他函数的代码不会因为意外的return语句而发生错误,这些语句应该是exit()调用。所以,把所有这些点结合在一起的结论是,使用return语句以main()结束程序是一个坏习惯,至少对C来说是这样。
return X;
exit(X);
dddzy1tm6#
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的 failure 代码的标准方法。因此,20世纪90年代早期的VAX/VMS C编译器并不解释来自main()的返回值,它只是将任何值返回给主机环境。但是如果你使用exit(),它会做标准要求的事情:将EXIT_SUCCESS(或0)转换为成功代码,并将EXIT_FAILURE转换为一般故障代码。要使用EXIT_SUCCESS,你必须将它传递给exit(),你不能从main()返回它。我不知道该编译器的更现代版本是否保留了这种行为。一个可移植的C程序看起来像这样:
EXIT_SUCCESS
EXIT_FAILURE
exit(0)
exit(EXIT_SUCCESS)
0
#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对退出值的约定比奇/偶更微妙。它实际上使用类似低三位的东西来编码严重性级别。然而,一般来说,奇数严重性级别表示成功或杂项信息,偶数严重性级别表示错误。
anhgbhbe7#
在C中,从main返回与用相同的值调用exit完全相同。C standard的第5.1.2.2.3节规定:如果main函数的返回类型是与int兼容的类型,则main函数初始调用的返回等价于以main函数返回的值为参数调用exit函数; 11)到达终止main函数的}返回值0。如果返回类型与int不兼容,则返回到宿主环境的终止状态是未指定的。C++的规则与其他答案中提到的有点不同。
yb3bgrhw8#
在main中,exit(0)和return(0)实际上是有区别的-当你的main函数被多次调用时。下面的程序
return(0)
#include <stdio.h> #include <stdlib.h> int main(int argc, char** argv) { if (argc == 0) return(0); printf("%d", main(argc - 1, argv)); }
Run as
./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。
8条答案
按热度按时间wlzqhblo1#
事实上,这是有区别的,但很微妙。它对C++有更多的影响,但差异很重要。
当我在
main()
中调用return
时,将为我的局部作用域对象调用析构函数。如果我调用exit()
,**不会为我的局部作用域对象调用析构函数!”重读它。exit()
不返回。这意味着,一旦我调用它,就没有“回退”,在该函数中创建的任何对象都不会被销毁。这通常没有什么影响,但有时会有影响,比如关闭文件(您肯定希望所有数据都刷新到磁盘?).请注意,即使您调用
exit()
,static
对象也会被清理。最后请注意,如果使用abort()
,则不会销毁任何对象。也就是说,没有全局对象,没有静态对象,也没有局部对象会被调用它们的析构函数。在选择退出而非返回时,请谨慎操作。
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
8ftvxx2r2#
另一个区别:
exit
是一个标准库函数,因此您需要包含标头并链接到标准库。为了说明(在C++中),这是一个有效的程序:但是要使用
exit
,你需要一个include:这就增加了一个额外的假设:从
main
调用exit
具有与返回零相同的副作用。正如其他人所指出的,这取决于您正在构建哪种可执行文件(即,谁在调用main
)。您是否正在编写一个使用C运行时的应用程序?Maya插件?Windows服务?驱动程序?每个案例都需要研究exit
是否等效于return
。IMHO使用exit
时,你 * 真正的意思是 *return
只会使代码更加混乱。OTOH,如果你真的是指exit
,那就用它吧。kmynzznz3#
至少有一个理由让我们更喜欢
exit
:如果您的任何atexit
处理程序引用main
中的自动存储持续时间数据,或者如果您使用setvbuf
或setbuf
将main
中的自动存储持续时间缓冲区分配给一个标准流,则从main
返回将产生未定义的行为,但调用exit
是有效的。另一种可能的用法(通常只用于玩具程序)是通过递归调用
main
退出程序。13z8s7eq4#
我总是使用
return
,因为main()
的标准原型说它确实返回int
。也就是说,某些版本的标准给予
main
特殊处理,并假设如果没有显式的return
语句,则返回0。给定以下代码:G++只为
foo()
生成一个警告,而忽略了main
缺少的返回:2ul0zpep5#
我强烈第二次评论R。关于使用exit()以避免在程序实际结束之前回收
main()
中的自动存储。main()
中的return X;
语句并不完全等同于对exit(X);
的调用,因为main()
的动态存储在main()
返回时消失,但如果调用exit()
,它不会消失。此外,在C或任何类似C的语言中,
return
语句强烈地暗示读者执行将在调用函数中继续,虽然这种执行的继续在技术上通常是正确的,如果你把调用main()
函数的C启动例程计算在内,当你打算结束这个过程时,它并不完全是你的意思。毕竟,如果你想在除了
main()
之外的任何其他函数中结束你的程序,你 * 必须 * 调用exit()
。在main()
中这样做也会使代码更具可读性,而且任何人都可以更容易地重构代码;也就是说,从main()
复制到其他函数的代码不会因为意外的return
语句而发生错误,这些语句应该是exit()
调用。所以,把所有这些点结合在一起的结论是,使用
return
语句以main()
结束程序是一个坏习惯,至少对C来说是这样。dddzy1tm6#
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的 failure 代码的标准方法。
因此,20世纪90年代早期的VAX/VMS C编译器并不解释来自
main()
的返回值,它只是将任何值返回给主机环境。但是如果你使用exit()
,它会做标准要求的事情:将EXIT_SUCCESS
(或0
)转换为成功代码,并将EXIT_FAILURE
转换为一般故障代码。要使用EXIT_SUCCESS
,你必须将它传递给exit()
,你不能从main()
返回它。我不知道该编译器的更现代版本是否保留了这种行为。一个可移植的C程序看起来像这样:
旁白:如果我没记错的话,VMS对退出值的约定比奇/偶更微妙。它实际上使用类似低三位的东西来编码严重性级别。然而,一般来说,奇数严重性级别表示成功或杂项信息,偶数严重性级别表示错误。
anhgbhbe7#
在C中,从
main
返回与用相同的值调用exit
完全相同。C standard的第5.1.2.2.3节规定:
如果main函数的返回类型是与int兼容的类型,则main函数初始调用的返回等价于以main函数返回的值为参数调用exit函数; 11)到达终止main函数的}返回值0。如果返回类型与int不兼容,则返回到宿主环境的终止状态是未指定的。
C++的规则与其他答案中提到的有点不同。
yb3bgrhw8#
在
main
中,exit(0)
和return(0)
实际上是有区别的-当你的main
函数被多次调用时。下面的程序
Run as
将导致以下输出:
然而,这一个:
无论参数如何,都不会打印任何内容。
如果你确信没有人会显式地调用你的
main
,那么从技术上来说,这并没有什么大的区别,但是为了保持更清晰的代码,exit
看起来会更好。如果你出于某种原因想调用main
-你应该根据你的需要调整它。说到C。