为什么 main() 没有编译器错误,最后没有返回? [英] Why no compiler error for main() without a return at the end?

查看:24
本文介绍了为什么 main() 没有编译器错误,最后没有返回?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写 C-brain 预告片:编写标准的 Hello-World 程序,不带分号.

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

int main(void){if (printf("Hello World!
"), exit(0), 0){/* 没做什么 */}}

但我不明白为什么我没有收到编译器错误(Visual Studio):

错误 C4716:'main':必须返回一个值

我尝试了其他声明了返回类型的函数,但缺少返回语句,并得到此编译器错误.

<小时>

请注意,我也尝试过:

int foo(void){if (printf("Hello World!
"), exit(0), true){/* 没做什么 */}}int main(void){富();}

并且不要在 foo 上收到编译器错误.如果我删除exit(0)",我确实 会收到编译器错误.显然编译器知道退出"是一个特殊的功能?这对我来说似乎很奇怪.

解决方案

正如 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 满足未定义行为的低要求,因此没有问题.

因此,即使问题中的程序 did 在结尾处运行 main()(导致未定义的行为),仍然不会发出警告.><小时>

原来的,不太好的答案:

在 ANSI/ISO 90 C 中,这是未定义的行为,因此 MS 确实应该产生错误(但标准不要求它们).在 C99 中,标准允许在 main() 的末尾隐含 return - C++ 也是如此.

所以如果编译成C++或C99,就没有错误,和return 0;一样.C90 导致未定义的行为(不需要诊断).

有趣的是(好吧,也许不是),在几个编译器(VC9、VC6、GCC 3.4.5、Digital Mars、Comeau)中,我用我的基本的,主要是默认选项集(我几乎总是使用的环境)尝试了这个对于代码片段的快速n-dirty测试)唯一警告缺少 return 语句的编译器是 VC6 在编译为 C++ 程序时(VC6 在编译为 C 时不会抱怨).

如果函数没有命名为 main,大多数编译器都会抱怨(警告或错误).为 C 编译时 Digital Mars 不会,而 GCC 不会为 C 或 C++ 编译.

I'm working on a C-brain teaser: Write the standard Hello-World program, without semi-colons.

My best answer so far is:

int main(void)
{
    if (printf("Hello World!
"), exit(0), 0)
    {
        /* do nothing */
    }
}

But I don't understand why I don't get compiler error (Visual Studio):

error C4716: 'main' : must return a value

I've tried other functions with a return-type declared, but missing a return-statement, and get this compiler error.


Note that I've also tried:

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

int main(void)
{
    foo();
}

And don't get a compiler error on foo. If I remove the "exit(0)", I do get the compiler error. Apparently the compiler has knowledge that "exit" is a special function? This seems very odd to me.

解决方案

As Jens pointed out in a comment, the posted code does not exhibit undefined behavior. The original answer here isn't correct and doesn't even really seem to answer the question anyway (on re-reading everything a few years later).

The question can be summed up as, "why doesn't MSVC issue warning C4716 for main() in the same circumstances it would for other functions"?

Note that diagnostic C4716 is a warning, not an error. As far as the C language is concerned (from a standards point of view anyway), there's never a requirement to diagnose a non-error. but that doesn't really explain why there's a difference, it's just a technicality that may mean you can't complain too much...

The real explanation for why MSVC doesn't issue the warning for main() when it does for other functions can really only be answered by someone on the MSVC team. As far as I can tell, the docs do not explain the difference, but maybe I missed something; so all I can do is speculate:

In C++, the main() function is treated specially in that there's an implicit return 0; just before the closing brace.

I suspect that Microsoft's C compiler provides the same treatment when it's compiling in C mode (if you look at the assembly code, the EAX register is cleared even if there's no return 0;), therefore as far as the compiler is concerned there is no reason to issue warning C4716. Note that Microsoft's C mode is C90 compliant, not C99 compliant. In C90 'running off the end' of main() has undefined behavior. However, always returning 0 meets the low requirements of undefined behavior, so there's no problem.

So even if the program in the question did run off the end main() (resulting in undefined behavior) there still wouldn't be a warning.


Original, not so good answer:

In ANSI/ISO 90 C, this is undefined behavior, so MS really should produce an error (but they aren't required to by the standard). In C99 the standard permits an implied return at the end of main() - as does C++.

So if this is compiled as C++ or C99, there's no error and it's the same as return 0;. C90 results in undefined behavior (which does not require a diagnostic).

Interestingly (well, maybe not), of the several compilers (VC9, VC6, GCC 3.4.5, Digital Mars, Comeau) I tried this on with my basic, mostly default options set (the environment I pretty much always use for quick-n-dirty testing of code snippets) the only compiler that warns about the missing return statement is VC6 when compiling as a C++ program (VC6 does not complain when compiling for C).

Most of the compilers complain (a warning or error) if the function is not named main. Digital Mars when compiling for C does not and GCC doesn't for C or C++.

这篇关于为什么 main() 没有编译器错误,最后没有返回?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆