16

如果一个函数的返回类型不是void,并且该函数没有返回任何内容,那么我猜编译器会返回一个垃圾值(可能被视为未初始化的值)。它发生在编译时,为什么不应该显示错误?

例如,

int func1() {
    return; // error
}

int func2() {
    // does not return anything
}

第二个func2应该抛出一个错误,但它不会。有什么原因吗?我的想法是,它可以看作是一个未初始化的值,所以如果我们需要在第二种情况下抛出错误,那么我们需要抛出错误,如果一个值未初始化,比如说

  int i;  // error
  int i = 6;  // okay

有什么想法,还是这是一个重复的问题?我感谢您的帮助。

4

4 回答 4

23

在 C++ 中,此类代码具有未定义的行为:

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

大多数编译器都会对与问题中的代码类似的代码产生警告。

C++ 标准不要求这是编译时错误,因为在一般情况下,很难正确确定代码是否真的在函数末尾运行,或者函数是否通过异常(或 longjmp或类似的机制)。

考虑

int func3() {
    func4();
}

如果func4()抛出,那么这段代码完全没问题。编译器可能看不到func4()(因为单独编译)的定义,所以不知道它是否会抛出。

此外,即使编译器可以证明 thatfunc4()没有抛出,它仍然必须证明func3()在它可以合法地拒绝程序之前实际被调用。这种分析需要检查整个程序,这与单独编译是不兼容的,这在一般情况下甚至是不可能的。

于 2012-03-30T02:10:29.827 回答
12

在 C 中,引用N1256 6.9.1p12:

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

因此,非 void 函数无法返回值是合法的(但不是一个好主意),但如果它这样做并且调用者尝试使用结果,则行为是未定义的。请注意,它不一定只返回一些任意值;就标准而言,一切皆有可能。

Pre-ANSI C 没有void关键字,因此编写不返回值的函数的方法是省略返回类型,使其隐式返回int。在返回值的函数中要求一个return语句会破坏旧代码。它还需要编译器进行额外的分析,以确定所有代码路径都命中了一条return语句;这种分析对于现代编译器来说是合理的,但在 C 首次标准化时可能是一个过度的负担。

C++ 稍微严格一些。在 C++ 中:

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

因此,无论调用者是否尝试使用(不存在的)结果,行为都是未定义的。

C 和 C++ 编译器当然可以警告缺少return语句,或者在不执行语句的情况下脱离函数末尾的控制路径return,但各自的标准不要求他们这样做。

于 2012-03-30T02:11:06.080 回答
6

在 C 中,只要调用代码不尝试使用返回值,非 void 函数在没有返回值的情况下完成实际上是合法的。

另一方面,return不带表达式的语句不允许出现在非 void 函数中。

对于第一种情况,C99 标准的相关部分是 §6.9.1:

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

对于第二种情况,第 6.8.6.4 节:

return没有表达式的语句只能出现在返回类型为 的函数中void

于 2012-03-30T02:09:20.640 回答
2

你的两个函数都是不正确的。它们之间的区别在于,当您的行为未定义时,您func1违反了有关如何return使用该语句的规则。func2您的return声明func1是非法的,实施必须对此进行诊断。您中缺少 return 语句func2是未定义的行为。大多数编译器都会对此进行诊断,但没有人必须这样做。

于 2012-03-30T02:10:02.800 回答