当我忘记编写函数的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)为什么这些结果?对此有什么一般规则吗?答案 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
内设置,因此返回值是调用该函数时该寄存器中的任何内容。