如果 main() 不返回 int 值会怎样?
Posted
技术标签:
【中文标题】如果 main() 不返回 int 值会怎样?【英文标题】:What happens if main() does not return an int value? 【发布时间】:2012-02-09 07:44:34 【问题描述】:我知道在 C 编译器中,main()
函数由 _start()
函数调用,其代码如下:
exit(main()); // return value of main is returned
当main()
不返回int
时_start()
如何工作,例如,如果它的返回类型是void
、float
或其他什么?
【问题讨论】:
我会映像函数指针转换,但我想听听知道真相的人的意见。等不及答案了。 :D C和C++对main返回值的限制不同 @fefe - 真的吗?我认为两者都需要返回 int - 得到标准的 para 数字以便我可以阅读?我有 C99 和 C++89、C++11 @Adrian 对于 C 是 5.1.2.2.1。 好的 C99 5.1.22.1.1 说“它应该用 int 的返回类型定义” c++14882 3.6.1.1 说“它应该有一个 int 类型的返回类型”和 c+ +14882-2011 3.6.1.1 说“它应该有一个 int 类型的返回类型”所以@fefe 他们似乎明确定义为在 C 和 C++ 之间是相同的 【参考方案1】:假设我们使用的是 Visual Studio 2012。
对于 C++ 程序,Visual Studio 允许将 void
指定为返回类型,即使 C++ 标准禁止这样做。根据标准,main()
必须在托管实现中返回 int
。
对于 C 程序,main()
允许任何返回类型,但返回 int
以外的其他内容会导致未指定的行为。例如,在 Visual Studio 2012 下,当程序在调试器中运行时,从double main()
返回0.0
会导致返回值0xcccccccc
(请参阅In Visual Studio C++, what are the memory allocation representations?)。
【讨论】:
【参考方案2】:C 标准不允许您返回除 int 或 void 之外的任何其他值——c 编译器专门测试 main 的签名以确保它兼容。
【讨论】:
C99(以及我在 C11 草案中看到的)没有提到void
。只有int
的返回类型被明确提到'它应以int
的返回类型定义',但不幸的是句子结束'或以其他一些实现定义的方式'(5.1.2.2.1)跨度>
由于 void return 5.1.2.2.1 的评论而被否决,没有提及 void return
@DanielFischer:我认为“以其他实现定义的方式”是指参数及其类型,而不是返回类型。
@dreamlax 我相信这就是目的。但就我对英语的了解而言,它可以被解读为允许任意实现定义的类型。我看到它是这样争论的。不幸的是,int
是 only 允许的返回类型(对于托管实现)并没有完全明确。【参考方案3】:
C 标准从未提及此_start
函数;我也不相信 C++ 会这样做。
在 1999 年 ISO 标准之前的 C 中,如果执行到达 main()
的末尾而不执行 return
语句,或者执行未指定值的 return
语句,则“返回终止状态到主机环境是未定义的”。在实践中,我见过这样的程序返回状态 1(失败)或内存中的某个任意值(例如调用的最后一个函数的结果)的实现。
1999 ISO C 标准改变了这一点:“到达终止 main 函数的 返回值 0”。这符合至少自 1998 年第一个 ISO C++ 标准以来 C++ 的规则。
(作为一种风格,我更喜欢在main
的末尾有一个显式的return 0;
,即使它不是严格要求的。这与int
以外的main
函数一致,并且它为 C99 之前的 C 编译器提供更好的可移植性。)
所有这些都假定main
定义为返回类型int
。这是 C 标准专门支持的唯一类型(int main(void)
或 int main(int argc, char *argv[])
或等效),但(托管)实现可能支持其他实现定义的定义。 C90 标准没有明确涵盖这种情况,但 C99 表示,“如果返回类型与 int 不兼容,则返回到宿主环境的终止状态是未指定的。”
C++ 标准有点不同。对于托管实现,main
必须定义为返回int
。参数是实现定义的,但必须支持两种标准形式的 C。
对于 C 或 C++ 中的托管实现,我知道没有充分的理由使用 int
以外的返回类型定义 main
。只需使用两个标准定义之一,就不会出现问题。
对于“独立实现”,“程序调用的函数的名称和类型
启动是实现定义的”。因此入口点可能会合法地返回void
或其他东西,甚至可能不会被称为main
。请注意,“独立实现”是“其中可能发生C程序执行的”没有任何
操作系统的好处”,通常是嵌入式系统。
【讨论】:
在该定义下,系统内核开发是否也算作“独立实现”?当然,如果操作系统内核到达入口点函数的末尾,那你就有问题了…… @MichaelKjörling:可能。在实践中,如果实现者说它是“独立的”(并且符合独立实现的较弱要求),则实现是“独立的”。 @KeithThompson:在 C99 之前,如果执行到达 main() 的末尾而不执行 return 语句,或者执行没有指定值的 return 语句,则“终止状态返回到主机环境未指定”不是未定义。 @PravasiMeet:您的报价来源是什么? C90 标准第 5.1.2.2.3 节说:“如果主函数执行一个没有指定值的返回,则返回给宿主环境的终止状态是 undefined。” (强调)当然“未指定”会更有意义。【参考方案4】:如果main
的返回类型不是int
,则返回值是实现定义的。
简而言之,对于main
,允许实现与int
具有不同的返回类型,但已知的实现都不支持int
以外的任何东西。
理想情况下,您需要参考您的平台和编译器的文档以查看它定义的确切行为,因为标准允许它具有灵活性。
参考:
C++03 标准:
3.6.1 主函数[basic.start.main]
实现不应预定义主要功能。该功能不得重载。 它的返回类型应该是 int 类型,否则它的类型是实现定义的。所有实现都应允许以下两种 main 定义:
int main() /* ... */
和
int main(int argc, char* argv[]) /* ... */
.....
【讨论】:
这不是说它必须有一个int
返回类型,但除此之外它可以接受任何参数,只要实现允许没有参数和argc
/argv
(即返回类型是int
,但main
函数的类型是实现定义的)。我在等咖啡安定下来,所以也许我没有任何意义......【参考方案5】:
C 的标准实现期望 main
返回 int
,因为它在 C 标准中是这样定义的。返回 int
以外的东西(或与 int
兼容的类型)通常会导致未定义的行为——这意味着无法知道会发生什么。
但是,C 也有非标准实现,例如,Plan 9 操作系统使用void main()
,here 是其实用程序的源代码列表。 Plan 9 C 代码与 K&R、ANSI、C99 或 C11 有很大不同。 Here's 解释 Plan 9 如何使用 C 语言的链接。
【讨论】:
【参考方案6】:如果main
不返回int
,那么您的程序格式错误并且行为未定义。任何事情都有可能发生。您的程序可能会崩溃,或者它可能会像没有任何问题一样运行。
假设main
返回的不是int
,并且您的编译器和链接器允许生成程序。不过,来电者并不知道这一点。如果调用者期望返回的int
值在 EAX (Intel) 寄存器中返回,那么它将读取该值以确定main
的返回值。如果您的错误main
在那里存储了float
值,那么它将被解释为int
。 (这并不意味着它会被截断。这意味着构成浮点值布局的位将改为构成int
。)如果您的错误main
返回void
,那么它没有'不在预期的寄存器中存储任何内容,因此调用者将获得之前存储在该寄存器中的任何值。
如果你的main
返回了一些类型,它希望存储调用者没有为它保留内存的某个地方(例如一个大结构),那么它最终会覆盖其他东西,也许是对清理很重要的东西关闭程序,导致程序崩溃。
【讨论】:
如何在 EAX 中存储浮点数? @KerrekSB - 好问题。虽然,在 80486 之前,它相对常见。毕竟,浮点数只是您使用特殊规则来操作的 32 位内容。 浮点数是否在寄存器中返回,@Kerrek?我不知道。在我在回答中描述的想象场景中,main
确实 - 不知何故 - 在调用者期望 int 去的地方存储了一个浮点数。行为是未定义的,所以我可以描述我想要的任何奇怪的工作方式!
@RobKennedy:浮点数通常在 FPU 的浮点寄存器中返回(例如 80387,或者可能是现代 MMX 的东西)。
x86 cdecl
在 ST0
中返回一个浮点数。新的 SIMD 寄存器仅用于 x64,其中XMM0
包含 FP 返回值。【参考方案7】:
在 C++ 中,如果从 main()
返回 int
以外的任何内容将是编译错误:
error: ‘::main’ must return ‘int’
在 C 语言中这是一个警告,您会得到一个浮点数,它被重新解释为 int
:例如,2.1F 将被重新解释为 224。
【讨论】:
仅供参考,gcc 默认不发出任何警告。 @shinkou 我刚试过 gcc - 它给了我warning: return type of ‘main’ is not ‘int’
我在 gcc 版本 4.5.2 (64bit) btw 上测试过。【参考方案8】:
该函数将返回一个实现定义的值。例如,在 C++ 中,main
隐式返回 0
。在这种void
main 的情况下,这将简单地由_start
返回。然而,几乎没有任何实现允许任意返回类型——它被嵌入操作系统中,进程以整数值退出。
【讨论】:
以上是关于如果 main() 不返回 int 值会怎样?的主要内容,如果未能解决你的问题,请参考以下文章