如果main()不返回int值会发生什么

What happens if main() does not return an int value?

本文关键字:什么 int 返回 main 如果      更新时间:2023-10-16

我知道在C编译器中,main()函数是由_start()函数调用的,该函数的代码如下:

exit(main()); // return value of main is returned

main()不返回int时,_start()如何工作?例如,如果其返回类型是voidfloat或其他类型?

如果main没有返回int,那么您的程序格式不正确,并且行为未定义。任何事情都有可能发生。你的程序可能会崩溃,或者它可能会像没有任何问题一样运行。

假设main返回的不是int,并且编译器和链接器允许生成该程序。打电话的人并不知道。如果调用者期望返回的int值返回EAX(Intel)寄存器,那么它将读取该值来确定main的返回值。如果有故障的main在那里存储了float值,那么它将被解释为int。(这并不意味着它会被截断。这意味着组成浮点值布局的位将组成int。)如果有故障的main返回void,那么它没有在预期的寄存器中存储任何内容,所以调用者将获得之前存储在该寄存器中的任何值。

如果main返回某种类型,它希望将其存储在调用方没有为其保留内存的地方(例如大型结构),那么它最终会覆盖其他内容,可能是对程序的干净关闭很重要的内容,从而导致程序崩溃。

C标准从未提及此_start函数;我不相信C++也能。

在1999年ISO标准之前的C中,如果在不执行return语句的情况下执行到main()的末尾,或者执行不指定值的return语句,则"返回到主机环境的终止状态未定义"。在实践中,我看到过这样的程序返回状态1(失败)或内存中的某个任意值的实现,例如调用的最后一个函数的结果。

1999年的ISO C标准改变了这一点:"达到终止main函数的}返回值0"。这与C++至少自1998年第一个ISO C++标准以来的规则相匹配。

(就风格而言,我更喜欢在main的末尾有一个显式的return 0;,即使这不是严格要求的。这与main之外的int函数一致,并且有助于更好地移植到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程序可以在没有任何操作系统的好处",通常是嵌入式系统。

函数将返回一个由实现定义的值。例如,在C++中,main隐式返回0。在void main的情况下,它只会由_start返回。然而,实际上没有允许任何任意返回类型的实现-它是在操作系统中烘焙的,进程带着整数值退出。

在C++中,从main():返回除int以外的任何内容都是编译错误

error: ‘::main’ must return ‘int’

在C中,这是一个警告,您将得到一个float重新解释为int:例如,2.1F将被重新解释为224。

C的标准实现期望main返回int,因为它在C标准中是这样定义的。返回int以外的内容(或与int兼容的类型)通常会导致未定义的行为—这意味着没有办法知道会发生什么。

然而,C也有非标准的实现,例如,Plan 9操作系统使用void main(),下面列出了它们的实用程序'源代码。计划9C代码与K&R、 ANSI、C99或C11。这里有一个链接,解释Plan 9如何使用C语言。

如果main的返回类型不是int,则返回值由实现定义
简言之,允许实现具有与mainint不同的返回类型,但没有一个已知实现支持除int之外的任何东西
理想情况下,您需要参考平台和编译器的文档,以了解它定义的确切行为,因为标准允许它具有这样做的灵活性。

参考:

C++03标准:

3.6.1主功能[basic.start.Main]

实施不应预先定义主要功能。此功能不应过载它应该有一个int类型的返回类型,否则它的类型是实现定义的。所有实施都应允许以下两个主要定义:

int main(){/*…*/}

int main(int argc,char*argv[]){/*…*/}

C标准不允许返回除int或void之外的任何其他值--C编译器专门测试main的签名以确保其兼容。

假设我们使用的是Visual Studio 2012。

对于C++程序,Visual Studio允许将void指定为返回类型,尽管这是C++标准所禁止的。根据该标准,main()在托管实现中必须返回一个int

对于C程序,main()允许任何返回类型,但返回int以外的内容会导致未指定的行为。例如,在Visual Studio 2012中,当程序在调试器中运行时,从double main()返回0.0会导致返回值0xcccccccc(请参阅在Visual Studio C++中,内存分配表示法是什么?)。