#include <stdio.h>
int add(int, int);
int main(int argc, char const *argv[])
{
int a = 2, b = 3;
printf("%d %d %d\n", a, b, add(a, b));
return 0;
}
int add(int a, int b) {
int c = a + b;
return;
}
上述程序的输出是2 3 5如何在没有明确返回的情况下返回c的add函数
答案 0 :(得分:5)
当一个应该返回一个值的函数没有这样做和时,调用者使用返回值,它是 undefined 。您可能观察到的任何事情纯粹是偶然/平台特定的行为,不能依赖。 C标准当然不能保证。
从C11草稿,6.9.1 Function definitions/12:
如果到达终止函数的},则为 函数调用由调用者使用,行为未定义。
答案 1 :(得分:1)
@ P.P.的回答是正确的:这是一种未定义的行为。
真正发生了什么,相反,它强烈依赖于编译器实现。 最可能的情况是调用函数无论如何都将获取返回值。由于被调用函数不返回任何值,这意味着调用函数将从堆栈中获取“随机” - 脏值。
我将为您提供GCC编译器的示例(没有任何优化):
这是函数add
的汇编代码:
push %rbp
mov %rsp,%rbp
mov %edi,-0x14(%rbp)
mov %esi,-0x18(%rbp)
mov -0x14(%rbp),%edx
mov -0x18(%rbp),%eax
add %edx,%eax
mov %eax,-0x4(%rbp)
nop
nop
pop %rbp
retq
如您所见,执行添加,存储在c
变量中。
结果值幸运地存储在%eax
寄存器中,但这并不是出于此目的。
这里有正确的功能的汇编代码:
push %rbp
mov %rsp,%rbp
mov %edi,-0x14(%rbp)
mov %esi,-0x18(%rbp)
mov -0x14(%rbp),%edx
mov -0x18(%rbp),%eax
add %edx,%eax
mov %eax,-0x4(%rbp)
mov -0x4(%rbp),%eax <====
pop %rbp
retq
如您所见,c
中存储的值已在%eax
寄存器中正确移动(带有<====
标记的指令。)
在main
函数(调用者)中,汇编为:
callq 0x400542 <add>
mov %eax,%ecx
正如您可以看到调用函数,在调用函数之后,取出应该在%eax
寄存器中的“返回值”。
这意味着尽管被调用者函数实际上返回了一个值,但调用者函数仍将采用返回值。
在我刚刚向您展示的示例中,调用者返回的值是%eax
注册。
总之,如果被调用者函数没有返回正确的值,那么调用者函数(main)将采用%eax
寄存器中存储的内容(其中)如果被调用者没有返回正确的值,则可以是脏值。)