我正在研究C-brain预告片:编写标准的Hello-World程序,没有分号。
到目前为止,我的最佳答案是:
int main(void)
{
if (printf("Hello World!\n"), exit(0), 0)
{
/* do nothing */
}
}
但我不明白为什么我没有得到编译器错误(Visual Studio):
error C4716: 'main' : must return a value
我已尝试使用声明的返回类型的其他函数,但缺少return语句,并且得到此编译器错误。
请注意,我也尝试过:
int foo(void)
{
if (printf("Hello World!\n"), exit(0), true)
{
/* do nothing */
}
}
int main(void)
{
foo();
}
不要在foo上遇到编译器错误。如果我删除“exit(0)”,我做会得到编译器错误。显然编译器知道“退出”是一个特殊的功能?这对我来说似乎很奇怪。
答案 0 :(得分:9)
正如Jens在评论中指出的那样,发布的代码没有表现出未定义的行为。这里的原始答案是不正确的,甚至似乎都没有回答这个问题(几年后重新阅读所有内容)。
这个问题可以概括为“为什么MSVC不会在与其他功能相同的情况下为main()
发出警告C4716”?
请注意,诊断C4716是警告,而不是错误。就C语言而言(无论如何从标准的角度来看),从来没有要求诊断非错误。但这并没有真正解释为什么会有差异,这只是一种技术性,可能意味着你不能抱怨太多......
为什么MSVC在为其他功能执行时不会发出main()
警告的真正解释,实际上只能由MSVC团队的某个人来回答。据我所知,文档并没有解释差异,但也许我错过了一些东西;所以我能做的就是推测:
在C ++中,main()
函数被特别处理,因为在结束括号之前有一个隐式return 0;
。
我怀疑微软的C编译器在C模式下进行编译时会提供相同的处理方法(如果查看汇编代码,即使没有return 0;
,EAX寄存器也会被清除),因此就编译器而言担心没有理由发出警告C4716。请注意,Microsoft的C模式符合C90标准,而不符合C99标准。在C90中,main()
的'结束'运行具有未定义的行为。但是,始终返回0满足未定义行为的低要求,因此没有问题。
因此,即使问题中的程序运行结束main()
(导致未定义的行为),仍然不会出现警告。
原创,答案不是很好:
在ANSI / ISO 90 C中,这是未定义的行为,因此MS确实应该产生错误(但标准不要求它们)。在C99中,标准允许在main()结尾处隐含 return
- 与C ++一样。
因此,如果将其编译为C ++或C99,则没有错误,它与return 0;
相同。 C90导致未定义的行为(不需要诊断)。
有趣的是(好吧,也许不是),在几个编译器(VC9,VC6,GCC 3.4.5,Digital Mars,Comeau)中,我尝试使用我的基本,主要是默认选项集(我几乎总是使用的环境)对于代码片段的快速脏测试)当编译为C ++程序时,唯一警告缺少返回语句的编译器是VC6(VC6在编译C时没有抱怨)。
如果函数未命名为 main
,大多数编译器会抱怨(警告或错误)。编译C时的数字火星没有,GCC不适用于C或C ++。
答案 1 :(得分:6)
如果你没有返回任何东西,程序将返回0。 见http://www.research.att.com/~bs/bs_faq2.html#void-main
答案 2 :(得分:2)
编译可能足够聪明,可以知道正在调用exit(0),它永远不会返回,因此不需要它。
答案 3 :(得分:1)
因为它不是错误 - 它是未定义的行为。见C99标准第6.9.1节第12段:
如果到达了终止函数的},并且调用者使用了函数调用的值,则行为是未定义的。
因此,当看到代码无法返回时,编译器可以自由地执行任何操作 - 它可以发出错误,警告或根本不发送任何内容。对于GCC,它默认情况下成功编译,没有警告或错误。使用-Wall
选项,它会发出警告。
main()
在C中是特殊的:它是唯一允许不返回值的函数。 C标准表示如果控件在没有main()
语句的情况下到达return
的末尾,则它会隐式返回0.这仅适用于main()
,所有其他非void函数必须返回值。
第5.1.2.2.3节:
如果main函数的返回类型是与int兼容的类型,则从中返回 对main函数的初始调用等效于使用main函数返回的值作为参数调用exit函数; 10)到达终止函数的} main函数返回值0.如果返回类型与int不兼容,则 返回到主机环境的终止状态未指定。
答案 4 :(得分:1)
C ++语言参考
退出功能
退出函数,在。中声明 标准包括文件STDLIB.H, 终止C ++程序。
作为参数提供的值 退出返回操作 系统作为程序的返回码或 退出代码。按照惯例,回归 代码为零意味着该程序 成功完成。
注意您可以使用常量 EXIT_FAILURE和EXIT_SUCCESS,已定义 在STDLIB.H中,表示成功或 你的程序失败了。
发出一个 来自主要的return语句 函数相当于调用 退出函数,返回值为 它的论点。
答案 5 :(得分:1)
由于各种原因,没有从main返回,或者更确切地说,没有返回主函数的终止'}'。典型案例包括永久循环,退出或中止之前。
在这种情况下,exit(0)
保证在到达main结束之前执行。编译器为什么要警告?你不会期待这些警告,不是吗?
int main (void) { for (;;) { /* do something useful */ } }
int main (void) { /* do something */; exit (0); }
如果
,我甚至会感到惊讶int main (void)
{
if (printf("Hello World!\n"), exit(0), true)
{
/* do nothing */
}
return 0;
}
不会导致warning: unreachable code: return 0
或某些事情。