如果main()不返回int值会发生什么
What happens if main() does not return an int value?
我知道在C编译器中,main()
函数是由_start()
函数调用的,该函数的代码如下:
exit(main()); // return value of main is returned
当main()
不返回int
时,_start()
如何工作?例如,如果其返回类型是void
、float
或其他类型?
如果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
,则返回值由实现定义
简言之,允许实现具有与main
的int
不同的返回类型,但没有一个已知实现支持除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++中,内存分配表示法是什么?)。
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- "类模板示例<int>;"语句对 C++11 是什么意思?
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 是什么导致了这种使用三进制而不是短整型的有符号int到无符号int转换
- 关于int :0有什么特别之处在C++
- C++ 未初始化的本地(非全局)int 数组中的元素类型到底是什么?
- ((int) a) 和 (int(a)) 之间的区别是什么?
- 在 C 和 C++ 中作为函数参数,int **a 和 int a[][] 之间有什么确切的区别
- map<string, int> m= {}; 在C++中是什么意思?
- 有什么方法可以使用 int 变量来完成组件名称吗?
- int x_ 和 int x 在C++中有什么区别
- 行 - " vector<int> used(adj.size(), 0); "是什么意思?
- int** a = new int*[n]();这个函数有什么作用?
- *(int*)&data[18]在这段代码中实际上做了什么?
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?
- 在 c++ 上,您通常使用什么 int 值、'255' 和十六进制值'0xff'?
- 有人可以向我解释什么[](int i){返回i%2 == 0;} 方法
- 更大的在集合中扮演什么<int>角色?
- 如何在矩阵中使用指针.这行代码的作用是什么:int r=**(++b);
- 编译器在这里做什么:int a = b * (c * d * + e)