9

好的,所以我在Ideone上搞砸了,不小心提交了这段代码,但令我惊讶的是,它实际上编译并运行输出值 0,here

#include <iostream>

using namespace std;

const int five(  )
{
        const int i = 5;
}

int main() {
        cout << five(  ) << endl;
        return 0;
}

然后我在 Visual Studio 和Codepad上尝试了这个,但是两者都未能编译,因为five()没有返回值,正如人们所期望的那样。我的问题当然是,为什么这在Ideone上编译得很好,即使我理解的代码是错误的并且不应该编译。

4

4 回答 4

14

简单明了(来自 C++11 6.6.3 “返回语句”):

从函数的末尾流出相当于没有值的返回;这会导致值返回函数中的未定义行为。

所以编译器几乎可以做它想做的任何事情。显然,诊断是我更喜欢编译器的东西,但有时很难诊断(比如返回在条件逻辑内部,并且永远不会到达函数的“结束”)。

请注意,我在 GCC 4.6.1 中收到以下警告(使用该Wall选项):

test.cpp:8:1: warning: no return statement in function returning non-void [-Wreturn-type]

我不确定 ideone 将哪些选项传递给 GCC(我想这-Wall对 ideone 使用的 4.3.4 版本会做同样的事情)。

一些相关资料:

在 C 语言中,声明返回值的函数在某些情况下实际上不这样做是可以的;在 C 中,如果实际使用了函数的返回值,它只会导致未定义的行为。准标准 C 并不总是支持该void类型,因此不返回任何内容的函数通常被int显式或隐式声明为 return 。从 C99 6.9.1/12“函数定义”开始:如果}到达终止函数的 ,并且调用者使用函数调用的值,则行为未定义。

main()此外,正如一些评论中提到的,C++ 和 C99 及更高版本对结尾的流出进行了特殊处理。

于 2012-07-15T20:22:06.807 回答
3

不从非 void 函数返回值是错误的,但并非所有编译器都将其视为错误——例如,GCC 仅在遇到此错误时才会发出警告。其他编译器可能偏执(他们是对的)并且不允许您编译此类代码。当然,编译器行为可以使用不同的开关和选项进行修改。

返回值 0 只是一个随机值——它可能同样是 255、-1 或任何其他垃圾,因为这样做是未定义的行为(除了 main,C99 指定应假定隐式返回值 0) .

于 2012-07-15T20:23:24.623 回答
3

ideone 似乎没有显示警告,它只在出现错误时显示编译器输出。在 ideone 使用的 GCC 版本(gcc 4.3)上,这不是一个错误,它只是一个警告。

于 2012-07-15T20:23:33.013 回答
2

代码具有未定义的行为。即使您所做的事情是错误的,编译器也不需要对其进行诊断。另一点是 ideone 使用的是现在相当旧的 gcc 版本。一个合理的当前版本的 gcc(例如,4.7)至少会给你一个警告,你的函数被声明为返回一个值,但没有——但不是默认情况下。你必须打开它-Wall来获得警告(但作为一般规则,我总是至少使用 -Wall 和 gcc)。

于 2012-07-15T20:24:39.537 回答