【问题标题】:What will a function return if there's no explicit 'return' [duplicate]如果没有明确的“返回”,函数将返回什么 [重复]
【发布时间】:2013-05-09 23:23:58
【问题描述】:

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

【问题讨论】:

  • 好问题。如果有人回答您的问题,我特别感兴趣,为什么 - 如果没有明确定义 - 这样做仍然不是错误。
  • @JoachimIsaksson return; 不是完全有效吗?
  • 如果在 Visual Studio 2008 及更高版本中编译,编译器会报错 func must return a value

标签: c function return undefined-behavior


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • return; 是有效的返回语句吗?
  • 如果函数被声明为返回 void 以外的值,则不会。
  • 6.9.1, paragraph 12 这是哪里来的??
  • @Thokchom,为什么会这样?从解释中可以看出,如果尝试使用返回值,它只会是 UB。 void 函数的调用者永远不会尝试这样做。
  • @Thokchom 在void 函数中,如果满足某个条件if (we_are_done) return; do_something_more();,则在某个时刻返回很有用。
【解决方案2】:

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

编辑

6.9.1 部分中的 draft C99 standard 函数定义12 段说:

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

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

【讨论】:

  • 不仅仅是调用约定,例如 x86 上 eax 的最后一个值。确实非常不确定。
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-04
    • 2021-07-02
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 2017-05-16
    • 1970-01-01
    相关资源
    最近更新 更多