函数的返回值是多少?

时间:2016-12-28 10:41:13

标签: c

#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函数

2 个答案:

答案 0 :(得分:5)

这是undefined behaviour

当一个应该返回一个值的函数没有这样做时,调用者使用返回值,它是 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寄存器中存储的内容(其中)如果被调用者没有返回正确的值,则可以是脏值。)