我用谷歌搜索,似乎无法找到这个简单问题的答案。
使用遗留代码库(最近移植到 Linux,并慢慢更新到新的编译器),我看到了很多
int myfunction(...)
{
// no return...
}
我知道函数的隐式返回 TYPE 是 int,但是当没有指定返回时,隐式返回 VALUE 是什么。我已经测试并得到了 0,但这仅适用于 gcc。这个编译器是特定的还是标准定义为 0?
编辑:12/2017 调整了接受的答案,基于它引用了更新版本的标准。
我用谷歌搜索,似乎无法找到这个简单问题的答案。
使用遗留代码库(最近移植到 Linux,并慢慢更新到新的编译器),我看到了很多
int myfunction(...)
{
// no return...
}
我知道函数的隐式返回 TYPE 是 int,但是当没有指定返回时,隐式返回 VALUE 是什么。我已经测试并得到了 0,但这仅适用于 gcc。这个编译器是特定的还是标准定义为 0?
编辑:12/2017 调整了接受的答案,基于它引用了更新版本的标准。
从新约中引用的'89标准:
从函数的末尾流出相当于没有表达式的返回。在任何一种情况下,返回值都是未定义的。
该标准通常表达预先存在的实现的实际行为。
这样的事情是可能的,但前提是函数的返回值从未被使用过。C11 标准在第 6.9.1 段中说:
如果到达终止函数的 },并且调用者使用了函数调用的值,则行为未定义。
(AFAIR 以前版本的标准有类似的措辞)
因此,将您必须使用的所有此类函数转换为函数将是一个好主意void
,因此此类函数的任何用户都不会被诱惑使用返回值。
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。
那只是未定义的行为;如果您不填充返回区域(例如,通常是x86 系列处理器上的 eax/rax),它将具有最后通过函数中的某些副作用设置的值。
请参阅对于不返回 void 的 C++ 函数是否必须使用 return 语句?这基本上是这个问题的副本(除了它被标记为 C++)。
如果return
语句始终不返回值,则最好将函数转换为并声明为返回void
:
void myfunction(...)
{
...
return;
...
}
如果函数中有一些return expr;
和一些return;
语句,那么您需要确定哪个是更好的行为,并使它们保持一致——要么总是返回一个值并将类型保留为原样,int
要么从不返回一个值并将类型更改为void
.
请注意,您需要声明修改为返回的函数void
(在标头中,除非它们是 - 或应该是 -static
并隐藏在单个源文件中),因为默认返回类型(假定的返回类型)int
不再有效。
在该函数中它可能始终为零,但在大多数体系结构(当然是 x86)上,return 语句将特定寄存器的内容移动到堆栈上的特定位置,调用者将检索该位置并将其用作其返回函数。
return 语句会将传递给它的变量放在该位置,以便它成为不同的值。我没有放置特定返回语句的经验是,返回的内容是相当随机的,您不能依赖它是同一件事。
我确信对于返回类型不是void
省略return
语句的函数来说,这是未定义的行为。在 C99 中有一个例外main
,如果return
省略该语句,则假定它隐式返回 0,但这不适用于任何其他函数。
它可能适用于特定的平台/编译器组合,但您永远不应该依赖这些细节。在代码中使用任何类型的未定义行为都会使其不可移植。但是,在遗留代码中看到未定义的行为是很常见的。