从主函数返回0是否必要,主函数的返回值如何有用?

6

我知道在C89中,从C程序的main函数中始终返回一个整数值0是惯例,就像这样:

int main() {

    /* do something useful here */

    return 0;
}

这是向操作系统返回“成功”结果的方法。虽然我认为自己在C语言方面只是个初学者(或最多是中级程序员),但到目前为止,我从来没有完全理解这一点的重要性。
我的猜测是,如果您将此程序的输出与另一个程序的输入连接起来,则此返回结果非常有用,但我不确定。我从未发现它有用,或者可能只是因为我不理解其意图。
我的问题:
1. 从C程序中始终返回零是否必要? 2. 如何使用main()函数的返回值?

https://dev59.com/7HVC5IYBdhLWcg3wtzkQ - Ciro Santilli OurBigBook.com
7个回答

7

当编写脚本时(如在Bash中或在Windows上的CMD.exe),您可以使用&&和||运算符链接一些命令。

规范地说,a && b将在a结果为零时运行b,而a || b将在a返回非零时运行b

如果您希望有条件地运行前一个命令成功后的命令,则这很有用。例如,如果要删除包含单词foo的文件,则会使用:

grep foo myfile && rm myfile

grep命令在匹配成功时返回0,否则返回非零值。


我认为你的回答很有用,但不是很清晰。你能给我一个例子吗?看起来你从谷歌搜索中剪切并粘贴了一些文本... - dvanaria
不,我没有复制粘贴,但是我不是以英语为母语的人,因此有时可能会困惑一些读者。 - Benoit
好的,说得也有道理,我认为他是在解释返回值可以用于条件判断。 - Alexander Rafferty
规范地说,a && b 将会在 a 的结果为零时运行 b。难道它不是一个关系运算符吗?只有当 a 返回 1 而不是零时才会运行吧? - Rohit Saluja

2

在现代C语言中,也就是C99(不确定C89是否适用),main函数的三种终止方式是等价的:

  • 在最后一个}处结束main函数
  • return 0
  • exit(0)

所有这些方式的背后意图(正如其他人所提到的)是为调用程序提供返回状态。


第一个是不正确的。除非有明确的“return”,否则C函数将返回它评估的最后一件事情。int main() { printf("Hello, world!\n"); }实际上会以14退出,因为printf()返回了它。 (如果你已经打开了编译器警告,就像你应该的那样,编译这个程序会抱怨控制到达了非void函数的结尾。)第二个只在main()中正确。 - Blrfl
7
在C99中,第一个语法是正确的(但在C89中不正确):“如果main函数的返回类型与int兼容,[...] 到达终止main函数的}时将返回值0。”(C99 5.1.2.2.3) - schot

2
“返回0”是一种惯例。当程序返回0时,可以假设它正常工作,而无需实际查看程序的操作(啊咳:D)。作为一种广泛使用的惯例,这种假设存在于许多地方。正如Benoit指出的那样,这是Shell(UNIX和Windows)和操作系统其他部分的情况。
因此,回答您的问题:
1.对于C程序,必须返回EXIT_SUCCESS或EXIT_FAILURE。但即使程序正常工作,也可以返回EXIT_FAILURE。
2.如果不返回0(EXIT_SUCCESS),则很可能其他程序会认为您的程序失败。
关于C++和C有一个相关的问题和出色的回答。What should main() return in C and C++?

1

返回值是程序执行的“结果”,0用于表示成功终止,而非零的返回值则表示失败或意外终止。

当您正常调用程序时,返回值对系统并不重要,但它可以有两个目的。其中之一是调试。在C++中最常用的编译器MSVC中,在程序完成执行后,您可以看到程序的返回值。这可以帮助您了解程序退出的“如何和为什么”。

另一个用途是当其他程序调用您的应用程序时,返回值可能会指示成功或传递结果。


0

当程序正确结束时应使用 EXIT_SUCCESS,而当程序没有正确结束时应使用 EXIT_FAILURE。EXIT_SUCCESS 是零,而零在任何操作系统上都是可移植的,而 EXIT_FAILURE 从 UNIX 到 Windows 等平台上都有所不同。这些常量在 stdlib.h 头文件中定义。

#include <stdlib.h>

int main()
{

    int toret = EXIT_SUCCESS;

    if ( !( /* do something useful here */ ) ) {
        toret = EXIT_FAILURE;
    }

    return toret;
}

当程序还是为控制台编写时,程序的返回代码更有用。如今,这种情况已经很少见了,除非你在一个非常专业的环境中工作(即使是这样,随着可用的工作流程工具的增加,这种情况也在改变)。

正如@Benoit所说,退出代码告诉操作系统操作是否成功。如果退出代码表示失败,那么你可以打破批处理程序的流程,因为它不太可能成功。

例如,编译器可以在编译成功时具有零的退出代码,而在编译失败时具有任何其他值。在Windows中,可以通过操作系统变量“errorlevel”访问此代码:

gcc helloworld.cpp -ohelloworld.exe
goto answer%errorlevel%
:answer0
copy helloworld.exe c:\users\username\Desktop
echo Program installed
goto end
:answer1
echo There were errors. Check your source code.
:end
echo Now exiting...

这个Windows批处理文件会在编译成功后将helloworld.exe“安装”到桌面上。由于您可以通过双击触发批处理文件的执行,因此这可以使您避免触及命令行进行编译。
当然,需要考虑到集成环境更好地管理它(如果退出代码不存在,则无法正常工作)。还要注意,在这个领域中,最好使用make。

https://en.wikipedia.org/wiki/Make_(software)

Make 运行正确还需要退出代码的支持。


C语言中正确的包含文件是"stdlib.h"而不是"cstdlib.h"。 - Jens Gustedt
我认为你声称退出代码“相当不常见”是相当奇怪的。虽然在许多领域中它们已经不再广泛使用,但这些领域也是C语言不再广泛使用的领域。在大多数情况下,如果您正在使用C语言,那么您很可能也会关心退出代码。 - Porculus
@Porculus,我试图传达的是(我认为我已经表达清楚了),这不是普通用户常见的,而是高级用户常见的。 - Baltasarq

0

我们可以从main()函数中返回任何整数。 现在,默认情况下,如果我们没有明确指定main()函数返回任何特定值,它将返回0。

实际上,返回0表示程序成功终止而没有任何错误,尽管这不是一条规则,但这就是它的工作方式。

如果我们明确返回一个非零数字,那么即使程序正确运行,但内部实际上意味着程序以某些错误或以意外结果终止。如果基于我们当前程序的返回值使用“&&”或“||”调用另一个程序,则这可能很有用。

您还可以使用此命令在Linux上检查先前执行的程序的返回值:

echo $?

0

你好,就像你所说的,如果程序作为更广泛的程序网络的一部分使用,返回零到程序环境可以让网络知道一切都很好(就像你所说的那样),但是你也可以让它返回1、2、3...(取决于发生了什么错误),以让你的代码网络知道出现了问题。同样地,你可以在“main”程序的末尾使用exit(0)或exit(1)来完成完全相同的操作。你可能会发现这个链接有用: http://en.wikipedia.org/wiki/Exit_status 希望能帮到你。杰克


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接