为什么C标准允许您不从函数返回值?

use*_*277 5 c gcc

我已经在gcc中成功编译并执行了以下代码:

#include <stdio.h>

int foo()
{

}

int main()
{
    int i = 12345;
    i = foo();
    printf("i is: %d", i);
}
Run Code Online (Sandbox Code Playgroud)

输出是:

i is: 0
Run Code Online (Sandbox Code Playgroud)

所以gcc允许我不从函数返回foo()foo()返回0.

这种行为只适用于gcc还是其他C标准也有它(基于我的理解,gcc不符合任何C标准)?

sep*_*p2k 10

如果函数缺少return语句¹,则没有C标准要求编译器产生错误或警告.

在所有C标准中,如果控制流在没有a return的情况下到达非void函数的末尾,则行为是未定义的,然后使用函数的返回值(如在代码中).

因此,如果"允许"意味着"将其指定为合法,定义明确的行为",那么C标准都不允许您的代码.如果你的意思是"不需要实现来产生错误",那么所有这些都可以.

请注意,i如果更改foo(不添加a return)的定义,示例程序中的值可以轻松更改.你不能依赖它为0.没有规则说"如果没有回报,则返回0" - 既不是标准也不是GCC的实施.根据标准,它是未定义的,在GCC中它只是当时在返回寄存器中发生的任何事情.


¹在一般情况下,这将是不可判定的.可以做一些例如Java所做的事情并定义规则,以便拒绝一些其他有效的函数定义,但没有一个C标准这样做.


Lun*_*din 8

gcc确实发出警告:

警告:控制到达非空函数的末尾[-Wreturn-type] |

(免责声明:我从不同版本的gcc得到不同的结果.确定,编译-Wall -Wextra -pedantic-errors.)

在这种情况下发生的事情不包括在C标准中.标准只是说(C11 6.9.1/12):

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

在您的情况下,调用者通过存储它来使用返回值i.所以这是未定义的行为 - C标准不包含该行为,编译器没有义务通知您.什么事情都可能发生.因此,在大多数情况下,这应该被视为一个错误.


Sou*_*osh 5

好的,该标准中没有任何内容可以阻止您编写非法代码,但是,它确实提到了这是未定义的行为。

引用C11第6.9.1章

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