Which one choose: exit or return?
我知道return和EDOCX1(link)之间的区别,但我不知道在哪里和什么时候选择一个而不是另一个。例如,从这个答案中,我理解return是一个更好的选择,但从另一个角度来说,我理解相反的选择。
例如:在这段代码中(从这个问题来看),使用exit()还是return更好?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| int read_file (char *filename , int **vet )
{
FILE *fin ;
if ( !(fin = fopen(filename ,"r")) )
{
perror(filename );
return -1;
}
* vet = malloc (10 * sizeof(int));
if ( *vet == NULL )
{
perror("Memory allocation error.
");
return -2;
}
/* ... */
return fclose(fin );
}
int main ()
{
char filename [100];
int *vet ;
if ( read_file (filename , &vet ) )
/* ??? exit(1) OR return -1 ??? */
return 0;
} |
一般情况下?
- 你写的exit(1) OR return -1 ???--1和-1不是等价的。
- @我把我的问题联系起来了:这是不同的。
- @用户也不例外。对那个问题的差异有一个全面的解释。没有正确的答案-这取决于你在做什么。在这种情况下,你的问题没有什么意义。
- @用户:不,一点也不。程序返回的状态值应该完全相同,无论是通过调用exit还是执行return语句返回的。对于某些函数,有一种使用负值返回错误的约定,但这不适用于main。唯一可移植的状态值是0、EXIT_SUCCESS和EXIT_FAILURE。(在类Unix系统上,负值映射到范围0..255,因此return -1;可能等同于return 255;。)
- @基思汤普森是的,对不起:在阅读你的回复之前,我写了我的评论!
- @KeithThompson:"程序返回的状态值应该完全相同,无论是通过调用exit还是执行返回语句返回的。"这不是严格意义上的。看我对原始问题的回答。
- @阿德里安·麦卡锡:事实上,我相信这是绝对正确的,至少对于符合标准的编译器来说是这样。有关详细信息,请参阅我对您答案的评论。
- @基思汤普森:你说得对。标准要求这是严格正确的,但它将一些实现置于一种不取胜的情况下,因此它们在这方面并不严格遵守标准。
在main函数中,exit(N)和return N;几乎完全相同(见下文)。
exit()终止程序的整个执行。return只从当前函数返回。(我知道你说过你知道区别,但我想完整)。
如果你在main,你可以使用你喜欢的任何一个。选择是风格的问题,我认为在哪种风格是最好的方面没有任何共识。您可以考虑使用exit,以防随后main中的代码被移到其他函数中。我会使用来自main的return来终止更正常的程序。
请注意,传递给exit或由return使用的值具有某种系统特定的含义。该值将返回到调用环境。0或EXIT_SUCCESS表示成功;EXIT_FAILURE表示失败。(EXIT_SUCCESS和EXIT_FAILURE是中定义的宏,与定义exit函数的头文件相同)。
任何其他值都具有系统特定的含义。特别是,有些系统(特别是虚拟机)上的exit(1)表示成功,而不是失败。在类Unix系统中,1表示失败,EXIT_FAILURE将定义为1。
您可以将EXIT_SUCCESS和EXIT_FAILURE与return或exit()一起使用。
另一方面,如果您需要指定一种以上的故障,那么EXIT_FAILURE就不够了。在类Unix系统上,可能在Windows上,0表示成功,1表示或多或少的一般性失败,其他小的正整数表示其他类型的失败。如果您需要的话,可以随意使用特定的值;您可能不关心您的程序在虚拟机上可能无法按预期工作。(我将为您使用的各种出口值定义常量,并清楚地说明它们在文档中的含义。)同样,您可以使用exit()或return,以更方便的为准。
我在上面说,来自main()的exit(N)和return N几乎相同。
在C语言中,main可以递归地调用自己。如果你的程序是在main中,而不是在main的初始调用中,那么return将终止当前main的执行,但不会终止程序;就像return对exit()对main以外的任何函数一样。递归地调用main几乎总是一个坏主意,所以这值得注意,但不值得担心。
此外,atexit()可用于注册程序退出时自动调用的函数。无论函数因exit()或return而终止,都将调用任何此类函数。区别(这是一个非常模糊的区别)是,exit()被main调用,return立即离开main。因此,如果您的一个atexit()注册函数引用了main中的一个局部变量,那么如果您调用exit()则该变量仍然存在,但如果您执行了return语句则不存在。你必须想方设法做到这一点,而且没有充分的理由这样做,所以你几乎肯定不必担心这个特别的问题。
- 如果我想区分错误?例如:我如何用EXIT_FAILURE编写一个类似exit(1)、exit(2)等代码?
- @用户:你不能用一种完全可移植的方式。但对于大多数系统(当然包括Linux和其他类似Unix的系统,可能也包括Windows),exit(1)表示或多或少的一般性故障,2或更高表示一些更具体的错误(例如,grep使用0表示匹配,1表示不匹配,2表示缺少文件等错误)。EXIT_FAILURE可能等于1,但如果需要特定的数值,只需写exit(1)、exit(2)等(或return 1、return 2)。我已经更新了我的答案;见第7段。
- +1用于atexit段。我以前从未考虑过这种行为上的差异。
如果在main中使用,两者都会做同样的事情,所以我会选择return 1,因为它更简单,而且不需要任何#include就可以工作。
当您想从某个函数终止或在您的main例程之外终止时,exit非常方便。
- 是的,但是return 1;的含义是系统特定的。(在Unix上,它表示成功;在vms上,它表示失败)。return EXIT_FAILURE;更可靠、更清晰,但需要#include 的支持。
- @基思汤普森,我完全同意。只是,问题的焦点是exit(1),而不是return 1,所以我的答案是。
这是你的选择。
标准C库启动代码可能看起来像:
无论如何,从主服务器返回可能会调用exit。我个人的选择是从main返回退出代码,因为它不会掩盖代码流。