如果在返回值为int的函数里,漏掉return,会发生什么情况?
编译工具:Code::Blocks 10.05,代码如下所示
#include <cstdio>
int f()
{
}
int main ()
{
printf("%d ",f());
printf("%d ",f());
printf("%d ",f());
return 0;
}
编译时,提示
In function 'int f()':|
warning: no return statement in function returning non-void|
但是能编译
Debug版本下结果如下:
1 2 2
Release版本下结果
0 0 0
下面分析一下为什么为发生这种情况:
从code:: blocks里面看到的 函数f的汇编代码
00401318 push %ebp
00401319 mov %esp,%ebp //正确的似乎是 mov %ebp %esp
0040131B leave
0040131C ret
如果函数f()如下定义
int f()
{
return 100;
}
则汇编代码是
00401318 push %ebp
00401319 mov %esp,%ebp
0040131B mov $0x64,%eax
00401320 leave
00401321 ret
接下来我们看一下整个main函数的汇编代码
00401322 push %ebp
00401323 mov %esp,%ebp
00401325 and $0xfffffff0,%esp
00401328 sub $0x10,%esp
0040132B call 0x401770 <__main>
00401330 call 0x401318 <f()>
00401335 mov %eax,0x4(%esp)
00401339 movl $0x403024,(%esp)
00401340 call 0x4019ac <printf>
00401345 call 0x401318 <f()>
0040134A mov %eax,0x4(%esp)//将返回值传递给%esp+0x04
0040134E movl $0x403024,(%esp)
00401355 call 0x4019ac <printf>
0040135A call 0x401318 <f()>
0040135F mov %eax,0x4(%esp)
00401363 movl $0x403024,(%esp)
0040136A call 0x4019ac <printf>
0040136F mov $0x0,%eax
00401374 leave
00401375 ret
从中我们可以看出,函数f()是将返回值通过EAX寄存器中,传递给调用它的代码。
如过我们漏掉了return intVal语句,在Debug模式下可能会导致,调用f()的代码得到的是上次的其他函数被调用的返回值。
在进入main之后EAX通常会被初始化为0x01.所以第一个f() 返回值为1.
printf 打印了“1 ”两个字符之后,返回值为2,所以第二个f()返回值为2。
printf 打印了“2 ”两个字符之后,返回值为2,所以第三个f()返回值为2。
在Release版本下,函数f()被优化,printf直接打印数字0。
401320: push %ebp
401321: mov %esp,%ebp
401323: and $0xfffffff0,%esp
401326: sub $0x10,%esp
401329: call 0x401760
40132e: movl $0x0,0x4(%esp)
401335:
401336: movl $0x403024,(%esp)
40133d: call 0x40199c
401342: movl $0x0,0x4(%esp)
401349:
40134a: movl $0x403024,(%esp)
401351: call 0x40199c
401356: movl $0x0,0x4(%esp)
40135d:
40135e: movl $0x403024,(%esp)
401365: call 0x40199c
40136a: xor %eax,%eax
40136c: leave
40136d: ret