C 为什么main()没有编译器错误,但结尾没有返回?

C 为什么main()没有编译器错误,但结尾没有返回?,c,compiler-errors,C,Compiler Errors,我正在做一个C-brain的小游戏:编写标准的Hello World程序,不带分号 到目前为止,我最好的答案是: int main(void) { if (printf("Hello World!\n"), exit(0), 0) { /* do nothing */ } } 但我不明白为什么我没有得到编译器错误(Visual Studio): 我尝试过其他声明了返回类型的函数,但缺少一条返回语句,因此出现了此编译器错误 请注意,我也尝试过: int

我正在做一个C-brain的小游戏:编写标准的Hello World程序,不带分号

到目前为止,我最好的答案是:

int main(void)
{
    if (printf("Hello World!\n"), exit(0), 0)
    {
        /* do nothing */
    }
}
但我不明白为什么我没有得到编译器错误(Visual Studio):

我尝试过其他声明了返回类型的函数,但缺少一条返回语句,因此出现了此编译器错误


请注意,我也尝试过:

int foo(void)
{
    if (printf("Hello World!\n"), exit(0), true)
    {
        /* do nothing */
    }
}

int main(void)
{
    foo();
}

不要在foo上得到编译器错误。如果删除“exit(0)”,则会出现编译器错误。显然,编译器知道“exit”是一个特殊的函数?这对我来说似乎很奇怪。

如果不返回任何内容,程序将返回0。
请参见

编译可能足够聪明,可以知道正在调用出口(0),该出口永远不会返回,因此不需要它。

因为它不是错误,而是未定义的行为。参见C99标准第6.9.1节第12段:

如果到达终止函数的},并且调用方使用了函数调用的值,则行为未定义

因此,当看到您的代码无法返回时,编译器可以自由地执行任何它想做的事情——它可以发出错误、警告或什么都不发出。在GCC的情况下,默认情况下它编译成功,没有警告或错误。使用
-Wall
选项,它会发出警告

main()
在C语言中很特殊:它是唯一不允许返回值的函数。C标准指出,如果控件到达
main()
的末尾时没有
return
语句,它将隐式返回0。这仅适用于
main()
,所有其他非void函数必须返回一个值

第5.1.2.2.3节:

如果主函数的返回类型是与int兼容的类型,则 对main函数的初始调用相当于以main函数返回的值作为参数调用exit函数;10) 到达终止 main函数返回一个值0。如果返回类型与int不兼容,则 返回到主机环境的终止状态未指定

从…起 C++语言参考

退出功能

退出函数,在 标准包括文件STDLIB.H, 终止C++程序。 作为参数提供给的值 退出返回到操作系统 系统作为程序的返回码或 退出代码。按照惯例,这是一种回报 代码为零表示程序 已成功完成

注意:您可以使用常量 退出失败和退出成功,已定义 在STDLIB.H中,表示成功或 你的程序失败了

签发 来自main的return语句 函数相当于调用 返回值为的exit函数 它的论点



正如Jens在评论中指出的,发布的代码不会表现出未定义的行为。这里的原始答案是不正确的,而且似乎根本无法回答这个问题(几年后重新阅读所有内容)

这个问题可以总结为,“为什么MSVC不在与其他函数相同的情况下为
main()
发出警告C4716”

注意,诊断C4716是一个警告,而不是错误。就C语言而言(无论如何从标准的角度来看),从来没有诊断非错误的要求。但这并不能真正解释为什么会有差异,这只是一个技术上的问题,可能意味着你不能抱怨太多

当MSVC对其他函数发出警告时,为什么MSVC没有对
main()
发出警告,真正的解释只能由MSVC团队中的某个人来回答。据我所知,这些文件并没有解释这种差异,但也许我遗漏了什么;所以我所能做的就是推测:

在C++中,<>代码>主()/<代码>函数被特别处理,即有隐式<代码>返回0;<代码>就在右大括号之前

我怀疑Microsoft的C编译器在C模式下编译时提供了相同的处理方式(如果查看汇编代码,即使没有
返回0;
,EAX寄存器也会被清除),因此就编译器而言,没有理由发出警告C4716。请注意,Microsoft的C模式与C90兼容,而不是与C99兼容。在C90中,
main()
的“结束运行”具有未定义的行为。但是,始终返回0满足未定义行为的低要求,因此没有问题

因此,即使问题中的程序确实运行了end
main()
(导致未定义的行为),也不会出现警告


原始的,不太好的回答:

在ANSI/ISO 90 C中,这是未定义的行为,因此MS确实应该产生错误(但标准不要求它们)。在C99中,标准允许在主()结尾的(< C++)./P>中包含隐含的<代码>返回<代码>。 <如果是编译为C++或C99,没有错误,它与<代码>返回0相同;<代码>。C90导致未定义的行为(不需要诊断)

有趣的是(也许不是),在几个编译器(VC9、VC6、GCC 3.4.5、Digital Mars、Comeau)中,我用我的基本选项集(主要是默认选项集)尝试了这一点(我几乎总是使用这个环境快速测试代码段)唯一的警告丢失的返回语句的编译器是VC6,编译为C++程序(VC6在编译C时不抱怨)。
如果函数未命名为
main
,大多数编译器都会抱怨(警告或错误)。当编译C时,数字火星不存在,GCC不适用于C或C++。

不返回main,或者更确切地说,不到达main函数的终止}完全出于各种原因。典型案例包括永久循环和退出或退出

int foo(void)
{
    if (printf("Hello World!\n"), exit(0), true)
    {
        /* do nothing */
    }
}

int main(void)
{
    foo();
}
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;
}