30

我用谷歌搜索,似乎无法找到这个简单问题的答案。

使用遗留代码库(最近移植到 Linux,并慢慢更新到新的编译器),我看到了很多

int myfunction(...)
{
// no return...
}

我知道函数的隐式返回 TYPE 是 int,但是当没有指定返回时,隐式返回 VALUE 是什么。我已经测试并得到了 0,但这仅适用于 gcc。这个编译器是特定的还是标准定义为 0?

编辑:12/2017 调整了接受的答案,基于它引用了更新版本的标准。

4

7 回答 7

24

从新约中引用的'89标准:

从函数的末尾流出相当于没有表达式的返回。在任何一种情况下,返回值都是未定义的。

该标准通常表达预先存在的实现的实际行为。

于 2012-04-09T20:12:35.570 回答
16

这样的事情是可能的,但前提是函数的返回值从未被使用过。C11 标准在第 6.9.1 段中说:

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

(AFAIR 以前版本的标准有类似的措辞)

因此,将您必须使用的所有此类函数转换为函数将是一个好主意void,因此此类函数的任何用户都不会被诱惑使用返回值。

于 2012-04-09T20:30:47.377 回答
14

return 语句永远不会在函数末尾强制执行,即使函数返回类型不是void。不需要诊断,也不是未定义的行为。

示例(定义的行为):

int foo(void)
{
}

int main()
{
    foo();
}

但是读取 的返回值foo是未定义的行为:

int bla = foo();  // undefined behavior

来自 C 标准:

C99,第 12 页上的 6.9.1)“如果到达终止函数的 },并且调用者使用了函数调用的值,则行为未定义。”

main函数是该规则的一个例外,就好像}在它中到达的main一样,就好像有一个return 0;语句一样。

C99 草案,第 13 页上的 5.1.2.2.3)...到达}终止main函数的返回值 0。

于 2012-04-09T20:32:10.027 回答
9

那只是未定义的行为;如果您不填充返回区域(例如,通常是x86 系列处理器上的 eax/rax),它将具有最后通过函数中的某些副作用设置的值。

请参阅对于不返回 void 的 C++ 函数是否必须使用 return 语句?这基本上是这个问题的副本(除了它被标记为 C++)。

于 2012-04-09T20:12:36.253 回答
2

如果return语句始终不返回值,则最好将函数转换为并声明为返回void

void myfunction(...)
{
    ...
    return;
    ...
}

如果函数中有一些return expr;和一些return;语句,那么您需要确定哪个是更好的行为,并使它们保持一致——要么总是返回一个值并将类型保留为原样,int要么从不返回一个值并将类型更改为void.

请注意,您需要声明修改为返回的函数void(在标头中,除非它们是 - 或应该是 -static并隐藏在单个源文件中),因为默认返回类型(假定的返回类型)int不再有效。

于 2012-04-09T20:19:08.893 回答
1

在该函数中它可能始终为零,但在大多数体系结构(当然是 x86)上,return 语句将特定寄存器的内容移动到堆栈上的特定位置,调用者将检索该位置并将其用作其返回函数。

return 语句会将传递给它的变量放在该位置,以便它成为不同的值。我没有放置特定返回语句的经验是,返回的内容是相当随机的,您不能依赖它是同一件事。

于 2012-04-09T20:13:55.850 回答
0

我确信对于返回类型不是void省略return语句的函数来说,这是未定义的行为。在 C99 中有一个例外main,如果return省略该语句,则假定它隐式返回 0,但这不适用于任何其他函数。

它可能适用于特定的平台/编译器组合,但您永远不应该依赖这些细节。在代码中使用任何类型的未定义行为都会使其不可移植。但是,在遗留代码中看到未定义的行为是很常见的。

于 2012-04-09T20:12:39.640 回答