如果没有明确的“返回”,函数将返回什么

时间:2013-05-15 11:47:11

标签: c function return undefined-behavior

当我忘记编写函数的return子句时,我遇到了这个问题,但gcc中没有警告或错误。我修复了它,但开始想知道为什么函数会在没有return的情况下返回无意义的。以下是我尝试过的一些例子:

#include "stdio.h"
#include "stdlib.h"

int func1 () {
        int i;
        i = 2;
}

int func2 (int a) {
        int i = a+3;
}

int func3 () {
        int i;
        for (i = 0; i <= 1; i++);
}

int main(void) {
        int a = 0;
        int b = 0;
        int c = 0;
        a = func1();
        printf("a = %d \n", a);
        b = func2(a);
        printf("b = %d \n", b);
        c = func3();
        printf("c = %d \n", c);
}

结果是:

a = 1 
b = 4 
c = 7 

我的问题:

1)为什么这些结果?对此有什么一般规则吗?
2)为什么要保留这个东西而不是报告错误?在某个地方可以某种程度上“有用”吗?

3 个答案:

答案 0 :(得分:7)

根据第6.9.1节第12段(C标准的N1570草案),这是不确定的行为:

  

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

如果调用者没有使用返回值,则行为不是未定义的。

仅仅未定义的行为不需要诊断消息,因此编译器没有义务发出警告。如果你要求(-Wreturn-type-Wall暗示),gcc会发出警告,并且默认会发出警告。

对于返回void以外类型的函数,return语句必须包含一个表达式,其值应按6.8.6.4第1段返回:

  

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

答案 1 :(得分:5)

这是undefined behavior,取决于所使用的calling convention。如果调用者期望寄存器中的结果,那么将使用寄存器中最后的值。

修改

部分6.9.1 功能定义 12 中的draft C99 standard说:

  

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

clang默认会发出警告,gcc会向-Wall发出警告,一般情况下您应该启用警告。

答案 2 :(得分:2)

在我的系统(gcc 4.5.3,linux)上,没有优化编译你的代码,我明白了:

main:
...
    call    func1
    movl    %eax, 28(%esp)
...

即。 func1的返回值是从eax寄存器中提取的,但该寄存器永远不会在func1内设置,因此返回值是调用该函数时该寄存器中的任何内容。