main函数的返回值范围

Posted

技术标签:

【中文标题】main函数的返回值范围【英文标题】:Return value range of the main function 【发布时间】:2011-07-06 04:11:11 【问题描述】:

标准对主要返回值范围有何看法? 最多只能说 255 个?

因为

int main(void)
return 256;

echo $? ;  # out 0

【问题讨论】:

另见ExitCodes greater than 255 — possible? 【参考方案1】:

标准没有说。 0EXIT_SUCCESSEXIT_FAILURE 具有(某种)特定的含义。其他任何事情都取决于实现。

目前,大多数基于 Unix 的系统仅支持 8 位返回值。 Windows 支持(至少)32 位返回值。我没有检查 64 位 Windows 是否支持 64 位返回值,但我比较怀疑,因为即使 64 位 Windows 通常仍然使用 32 位 int。

【讨论】:

在 64 位 Windows 上我尝试了 cmd /c "exit 4000000000" 然后 echo %errorlevel% 并返回 -294967296 => 32 位 POSIX 标准确实 非常清楚地定义了这一点:pubs.opengroup.org/onlinepubs/9699919799/functions/_exit.html @MikeFrysinger:它说:“......完整的值应从 waitid() 和传递给 SIGCHLD.v 的信号处理程序的 siginfo_t 中可用”,但没有说任何关于该“完整值”是 16、32 还是 64 位。我看不到对 int 大小的特定于 POSIX 的定义的交叉引用,并且 C 标准允许上述任何一种。这可能是关闭进程时需要进行的 other 清理的一个不错的定义,但就返回值中的位数而言(充其量)似乎是平庸的。 虽然您是正确的,但它们并没有明确规定 int 的大小,POSIX 和 C 标准都要求 INT_MAX 必须至少为 2147483647 (2^31-1) 并且 INT_MIN 必须在大多数 -2147483647 (-2^31+1),并且“int”类型的对象必须能够表示 [INT_MIN, INT_MAX],所以我认为可以安全地假设 sizeof(int) 是(至少)32 - 任何 POSIX 兼容系统上的位。 pubs.opengroup.org/onlinepubs/9699919799/basedefs/… 你也可以这样看:main的返回值是一个“int”。 POSIX (2016+) 将其全部价值定义为在使用 waitid 或 sigaction/etc...+SA_SIGINFO 时可供父进程使用。【参考方案2】:

正如其他人所说,C 和 C++ 标准除了声明之外根本不限制返回值

    main() 返回一个 int(具有实现定义的大小),并且 零(或EXIT_SUCCESS)是成功返回,EXIT_FAILURE 是不成功返回。

它确实指定了一个没有明确返回值的main() 被视为返回零。

在这种情况下,返回值的解释取决于等待进程完成的进程(通过调用wait()waitpid()waitid())。 wait()waitpid() 是较旧的 POSIX 函数,它们仅指定 the least significant eight bits of the return value shall be available to a waiting parent process。 POSIX:2008 标准添加了waitid() 作为通用等待方法,可以访问子进程的完全退出状态。

在 fork 子进程后,父进程调用 wait*() 函数之一进入休眠状态,直到 fork 进程完成(例如,从 main() 返回,调用 exit()abort() 或其他东西)。 wait()waitpid() 函数通过指向整数的指针返回状态。调用者使用WIFEXITED(status_val)WEXITSTATUS(status_val) 宏提取实际退出状态。后者由 POSIX 定义,需要返回 the low-order 8 bits of the status argumentwaitid() 函数使用指向siginfo_t 结构的指针来返回进程的状态信息。 si_status 成员包含Status Information 中描述的完整状态值。

基本上,退出状态的值在旁观者的眼中。 ANSI/ISO 规范是开放式的。 POSIX 套件有多种方法可以等待进程完成并获取其退出状态。 POSIX 还将spawn() 定义为exec() 的轻量级版本,它对退出状态值有自己的一组约束。 Shell 有进一步限制结果值的习惯——GNU's bash 将返回状态限制为 7 位,POSIX-compliant shell 将退出状态值限制为 8 位。 FWIW,大多数人都同意将您的返回值限制为lower than 64 seems to be safe。

【讨论】:

【参考方案3】:

在类 Unix 系统上,退出代码是 0 到 255 之间的数字。你可以返回任何东西,但在 Linux 中它是修改为 256。看看here 以获得关于 Linux 返回码的一个很好的解释。还有一个Wikipedia article on the topic 简要介绍了 Windows 的退出代码。

【讨论】:

说“模”是一种误导,因为它实际上是一个 8 位掩码。 exit(-1) 对大多数调用者会产生 255 的值(因为 -1&0xff == 255),但 -1%256 == -1,而不是 255。是的,它从有符号的 32 位变为无符号的 8 位. @MikeFrysinger “模”是正确的术语。您在此处描述的 % 运算符是除法的余数,但大多数现代编程语言实际上使用 % 进行取模,这适用。 Modulo 不是我已经解释过的正确术语。 % == modulo 的事实不相关,因为手头的操作不是 %【参考方案4】:

C 标准对退出代码没有特别的限制,关于main 的返回值的段落代表了关于exit() 函数的文档,它反过来说:

如果status 的值为零或EXIT_SUCCESS,则返回成功终止状态的实现定义形式。如果status的值为EXIT_FAILURE,则返回一个实现定义的状态不成功终止形式。否则返回的状态是实现定义的。

除了EXIT_SUCCESS/EXIT_FAILURE 准则之外,它基本上意味着“随心所欲”。 :)

正如在一条评论中所说,在 POSIX 系统上实际上只考虑退出代码的低 8 位这一事实只是一种 UNIX 主义,源自 wait 系统调用的设计方式(退出状态必须被打包在wait返回值的低8位),与C标准无关。

一个反例是 Windows,其中考虑传递给 exit/return 的整个值(只要它不大于 DWORD1,但我不认为他们会让intDWORD 大,这会破坏很多代码)。


1、因为为返回这个值而保留的GetExitCodeProcess参数是DWORD *

【讨论】:

事实上ExitProcess函数接收到UINT【参考方案5】:

在 Unix 上,等待系统调用设置一个 int 类型的状态值打包为 具有各种类型孩子的位域 终止信息。如果孩子 通过退出终止(如确定 通过 WIFEXITED 宏;通常 另一种选择是它死于 未捕获的信号),SUS指定 状态值的低 8 位 包含退出状态;这个可以 使用 WEXITSTATUS 检索 wait.h 中的宏。因此,在 Unix 退出状态仅限于值 0-255,无符号8位范围 整数。

类 Unix 系统通常使用 成功和非零的约定 零错误。一些约定 已经发展到相对 各种错误代码的含义;为了 示例 GNU 建议使用 高位设置被保留 严重错误,而 FreeBSD 有 记录了一组广泛的 首选的解释。

C99 标准只定义了 0 和 1。但是,允许使用其他值。

请参阅Exit Status wiki 了解更多信息。

【讨论】:

我不记得曾在标准的任何地方看到过1 的值。在 ANSI/ISO 标准中,只有 0EXIT_SUCCESSEXIT_FAILURE 被明确称为状态值。 @D.Shawley:你是对的。但我从未见过 EXIT_SUCCESS 与 #define EXIT_SUCCESS 0#define EXIT_FAILURE 1 的 EXIT_FAILURE 不同。【参考方案6】:

您返回类型int。您应该能够返回可以存储在int 中的任何值。 int 的确切大小取决于实现,所以我不能给你一个确切的范围。

【讨论】:

话虽如此,您的 shell 可能支持的返回值范围有限。然而,这不是 C 标准的一部分。 即使返回类型是int,也只有低8位包含退出状态。 @Vlad:这只是一个 UNIX 主义,标准没有说明它。 @Vlad Lazarenko-根据 C 标准,这是不正确的。那是 POSIX 特定的行为。 OP 询问了 standard 的规定。 我实际上告诉了 C 标准的规定,0 和 1 :-) 由于问题是在 unix 范围内提出的 ($?),我说为什么 0-255...【参考方案7】:

5.1.2.2.3 程序终止 1 如果主函数的返回类型是 与 int 兼容的类型,返回 从最初的调用到 main 函数相当于调用 退出函数并返回值 由 main 函数作为其参数; 10) 到达终止 main 函数返回值 0。如果 返回类型不兼容 int,返回的终止状态 到宿主环境是未指定的

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

即,它不需要返回任何东西。然而,它强烈地说明了通常的定义是什么。几乎暗示它们是标准的,但有一张免狱卡,这意味着它可以是任何东西。

【讨论】:

以上是关于main函数的返回值范围的主要内容,如果未能解决你的问题,请参考以下文章

main函数

C语言中的main()函数返回值是啥?

从更高范围返回左值的 Lambda 函数

为啥 Rust 在 main 函数中没有返回值,以及如何返回值?

c++ 让main函数循环运行大家都是怎么做的?

为啥 main() 函数不返回浮点值?