我知道在C编译器中main()
函数由_start()
函数调用,该函数的代码如下:
exit(main()); // return value of main is returned
当_start()
未返回main()
时,int
如何工作,例如,如果其返回类型为void
,float
或其他什么?< / p>
答案 0 :(得分:14)
如果main
没有返回int
,那么您的程序格式错误,行为未定义。任何事情都可能发生。您的程序可能会崩溃,或者它可能会运行,好像没有任何错误。
假设main
返回int
以外的内容,您的编译器和链接器允许编写程序。但是,来电者并不知道这一点。如果调用者希望在EAX(Intel)寄存器中返回返回的int
值,那么它将读取以确定main
的返回值。如果您的错误main
存储了float
值,那么它将被解释为int
。 (这并不意味着它会被截断。这意味着构成浮点值布局的位将改为构成int
。)如果您的错误main
返回{{1然后它没有在预期的寄存器中存储任何内容,因此调用者将获得之前存储在该寄存器中的任何值。
如果你的void
返回某种类型,它希望存储一个调用者没有为其保留内存的地方(例如一个大结构),那么它最终将覆盖其他东西,也许是重要的东西。程序的干净关闭,导致程序崩溃。
答案 1 :(得分:14)
C标准从未提及此_start
函数;我不相信C ++也会这样做。
在1999 ISO标准之前的C中,如果执行到main()
的末尾而没有执行return
语句,或者执行没有指定值的return
语句,然后“返回主机环境的终止状态未定义”。在实践中,我已经看到这样的程序返回状态为1(失败)的实现,或者内存中的某些任意值,例如被调用的最后一个函数的结果。
1999 ISO C标准改变了这一点:“达到}终止 main 函数返回值0”。这符合C ++至少自1998年第一个ISO C ++标准以来的规则。
(作为一种风格,我更喜欢在return 0;
的末尾有一个明确的main
,即使它并非严格要求。这与int
以外的函数一致main
,它为C99 C编译器提供了更好的可移植性。)
所有这些都假设main
的定义返回类型为int
。这是C标准(int main(void)
或int main(int argc, char *argv[])
或等效)特别支持的唯一类型,但(托管)实现可能支持其他实现定义的定义。 C90标准没有明确涵盖这种情况,但C99说,“如果返回类型与int不兼容,则返回到主机环境的终止状态未指定。”
C ++标准有点不同。对于托管实施,必须<{1}} 定义以返回main
。参数是实现定义的,但必须支持C的标准形式。
对于C或C ++中的托管实现,我没有充分理由使用int
以外的返回类型定义main
。只需使用两个标准定义中的一个,就不会出现问题。
对于“独立实现”,“在程序中调用的函数的名称和类型
启动是实现定义的。所以入口点可能合法地返回int
或其他东西,它甚至可能不被称为void
。注意“独立实现”是一个“其中C程序执行可能没有任何执行
操作系统的好处“,通常是嵌入式系统。
答案 2 :(得分:8)
该函数将返回实现定义的值。例如,在C ++中,main
隐式返回0
。在void
main的情况下,这只会由_start
返回。但是,几乎没有任何实现可以允许任何返回类型 - 它被烘焙到操作系统中,进程以整数值退出。
答案 3 :(得分:7)
在C ++中,从int
返回main()
以外的任何内容将是编译错误:
error: ‘::main’ must return ‘int’
在C中它是一个警告,你将浮动重新解释为int
:例如,2.1F将被重新解释为224。
答案 4 :(得分:2)
C的标准实现期望main
返回int
只是因为它在C标准中以这种方式定义。返回int
以外的其他内容(或与int
兼容的类型)通常会导致未定义的行为 - 这意味着无法判断将会发生什么。
但是,存在C的非标准实现,例如,Plan 9操作系统使用void main()
,here是其实用程序源代码的列表。 Plan 9 C代码与K&amp; R,ANSI,C99或C11完全不同。 Here's一个解释计划9如何使用C语言的链接。
答案 5 :(得分:2)
如果main
的返回类型不是int
,则返回值是实现定义的。
简而言之,对于int
,允许实现具有与main
不同的返回类型,但是除了int
之外,所有已知实现都不支持任何其他类型。
理想情况下,您需要参考平台和编译器的文档,以了解它定义的确切行为,因为标准允许它具有灵活性。
参考:
C ++ 03标准:
3.6.1主要功能[basic.start.main]
实现不应预定义主函数。此功能不应过载。 它的返回类型应为int类型,否则其类型为实现定义。所有实现都应允许以下两个主要定义:
int main(){/ * ... * /}
和
int main(int argc,char * argv []){/ * ... * /}
.....
答案 6 :(得分:0)
C-standard不允许返回除int 或void 之外的任何其他值--c编译器专门测试main的签名以确保它是兼容的。
答案 7 :(得分:0)
假设我们正在使用Visual Studio 2012。
对于C ++程序,Visual Studio允许将void
指定为返回类型,即使C ++标准禁止这样做。根据标准,main()
必须在托管实施中返回int
。
对于C程序,main()
允许任何返回类型,但返回int
以外的其他内容会导致未指定的行为。例如,在Visual Studio 2012下,从0.0
返回double main()
会导致在调试器中运行程序时返回值0xcccccccc
。(请参阅In Visual Studio C++, what are the memory allocation representations?)。 p>