对函数返回值感到困惑

时间:2014-04-11 14:45:12

标签: c++ return-value

#include<iostream>
using namespace std;
int Fun(int x)
{
    int sum=1;
    if(x>1)
        sum=x*Fun(x-1);
    else
        return sum;
}
int main()
{
    cout<<Fun(1)<<endl;
    cout<<Fun(2)<<endl;
    cout<<Fun(3)<<endl;
    cout<<Fun(4)<<endl;
    cout<<Fun(5)<<endl;
}

此函数用于计算整数的阶乘。在x>1的分支中,函数Fun没有返回值。所以这个功能不应该返回正确的答案。

但是当测试fun(4)或其他一些例子时,会出现意外的正确答案。为什么呢?

此功能的汇编代码为(调用Fun(4)):

0x004017E5  push   %ebp
0x004017E6  mov    %esp,%ebp
0x004017E8  sub    $0x28,%esp
0x004017EB  movl   $0x1,-0xc(%ebp)
0x004017F2  cmpl   $0x1,0x8(%ebp)
0x004017F6  jle    0x40180d <Fun(int)+40>
0x004017F8  mov    0x8(%ebp),%eax
0x004017FB  dec    %eax
0x004017FC  mov    %eax,(%esp)
0x004017FF  call   0x4017e5 <Fun(int)>
0x00401804  imul   0x8(%ebp),%eax
0x00401808  mov    %eax,-0xc(%ebp)
0x0040180B  jmp    0x401810 <Fun(int)+43>
0x0040180D  mov    -0xc(%ebp),%eax
0x00401810  leave
0x00401811  ret

可能是这个原因:和的值保存在寄存器eax中,返回值也保存在eax中,因此{{1}返回正确的结果。

6 个答案:

答案 0 :(得分:1)

当你的程序传递if条件时,没有return语句完成该函数。您获得的数字是未定义行为的结果。

int Fun(int x)
{
    int sum=1.0;
    if(x>1)
        sum=x*Fun(x-1);
    else
        return sum;

    return x; // return something here
}

答案 1 :(得分:1)

通常,EAX寄存器用于存储返回值,ad也用于存储其他内容。

因此,即使您不打算这样做,在函数返回之前加载到该寄存器的任何内容都将是返回值。

您可以使用-S选项生成汇编代码,并在&#34; ret&#34;之前查看EAX发生了什么。指令。

答案 2 :(得分:0)

the comment所述,这是未定义的行为。使用g ++,我收到以下警告。

warning: control reaches end of non-void function [-Wreturn-type]

在Visual C ++上,默认情况下警告会提升为错误

error C4716: 'Fun' : must return a value

当我disabled the warning并运行生成的可执行文件时,Fun(4)给了我1861810763

那么为什么它可以在g ++下运行?在编译期间,条件语句将转换为测试和跳转(或者getos)。该函数必须返回一些内容,编译器生成的最简单的代码如下所示。

int Fun(int x)
{
    int sum=1.0;
    if(!(x>1))
        goto RETURN;
    sum=x*Fun(x-1);
RETURN:
    return sum;
}

这与您的反汇编一致。

当然,您不能依赖于未定义的行为,如Visual C ++中的行为所示。由于这个原因,许多商店都制定了将警告视为错误的政策(同样在comment中建议)。

答案 3 :(得分:0)

只需从代码中删除else

int Fun(int x)
{
    int sum=1;
    if(x>1)
        sum=x*Fun(x-1);

    return sum;
}

答案 4 :(得分:0)

您拥有的代码有几个错误:

  • 您为int分配了值1.0(将被隐式转换/转换),而不是错误,但不优雅。
  • 你在条件规则中有一个return语句,所以当if为真时你只会得到一个返回

如果你通过删除else解决了返回的问题,那么一切都会好的:)

至于为什么它与4作为输入一起使用,这取决于您的环境的随机机会/某些属性,因为您发布的代码应该无法运行,因为在计算因子时,总会有一个实例一个正的int,其中x = 1,不会产生任何回报。

顺便说一句,这里有一个更简洁/简洁的功能:对于如此简单的功能,您可以考虑使用ternary operator并使用如下函数:

int factorial(int x){ return (x>1) ? (x * factorial(x-1)) : 1;}

这是我用于我的阶乘的函数,并且在过去30年左右的时间里已经存在于库中(自我的C日起):)

答案 5 :(得分:0)

来自C标准:

  

离开函数末尾相当于没有返回   值;这会导致值返回时出现未定义的行为   功能。

您的情况与此情况相同:

int fun1(int x)
{
    int sum = 1;
    if(x > 1)
        sum++;
    else
        return sum;

}
int main()
{
    int b = fun1(3);
    printf("%d\n", b);
    return 0;
}

它在我的机器上打印2。 这是calling convention并且取决于体系结构。返回值是最后一次表达式求值的结果,存储在eax寄存器中。