3

当我忘记写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)为什么要保留这个东西而不是报错?它可以在某处以某种方式“有用”吗?

4

3 回答 3

7

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

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

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

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

对于返回除 之外的类型的函数,根据 6.8.6.4 第 1 段voidreturn语句必须包含应返回其值的表达式:

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

于 2013-05-15T11:56:35.867 回答
5

这是未定义的行为,将取决于所使用的调用约定。如果调用者期望寄存器中的结果,那么将使用寄存器中最后的任何值。

编辑

功能定义12段中的C99 标准草案说:6.9.1

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

clang默认情况下会发出警告,并gcc会用 发出警告-Wall,通常您应该启用警告。

于 2013-05-15T11:48:39.507 回答
2

在我的系统(gcc 4.5.3,linux)上,编译你的代码没有优化,我得到这个:

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

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

于 2013-05-15T11:55:36.717 回答