C++ 对函数返回值感到困惑

C++ 对函数返回值感到困惑,c++,return-value,C++,Return Value,这可能是原因:sum的值保存在寄存器eax中,返回值也保存在eax中,因此Fun返回正确的结果。当程序通过if条件时,没有返回语句完成函数。您得到的数字是未定义行为的结果 0x004017E5 push %ebp 0x004017E6 mov %esp,%ebp 0x004017E8 sub $0x28,%esp 0x004017EB movl $0x1,-0xc(%ebp) 0x004017F2 cmpl $0x1,0x8(%ebp) 0x004017F6

这可能是原因:sum的值保存在寄存器
eax
中,返回值也保存在
eax
中,因此
Fun
返回正确的结果。

当程序通过
if
条件时,没有返回语句完成函数。您得到的数字是未定义行为的结果

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
如中所述,这是未定义的行为。使用g++时,我得到以下警告

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

    return x; // return something here
}
在VisualC++中,默认情况下,警告被提升为错误

warning: control reaches end of non-void function [-Wreturn-type]
当我运行生成的可执行文件时,
Fun(4)
给了我
1861810763

那么为什么它可以在g++下工作呢?在编译期间,条件语句被转换为测试和跳转(或GOTO)。函数必须返回一些东西,编译器可能生成的最简单代码如下所示

error C4716: 'Fun' : must return a value
这与您的拆卸是一致的


当然,你不能依赖于未定义的行为,如VisualC++中的行为所示。出于这个原因,许多商店都有将警告视为错误的策略(也如a中所建议的)。

只需从代码中删除
else

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

您的代码有几个错误:

  • 您将
    int
    赋值为1.0(将隐式转换/转换),这不是错误本身,而是不雅观的
  • 在条件中有一个return语句,因此只有当
    为true时才会得到返回
如果您通过删除else来解决退货问题,那么一切都会很好:)

至于为什么它使用4作为输入,这取决于随机机会/您环境的某些属性,因为您发布的代码应该无法运行,因为在计算正整数的阶乘时,总会有一个实例,其中x=1,并且不会生成返回

作为一个旁白,这里有一个更简洁/简洁的函数:对于这样简单的函数,你可以考虑并使用如下函数:

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

    return sum;
}

这是我用于阶乘的函数,在过去30年左右的时间里(从我的C天开始)我一直在库中使用它:)

通常,EAX寄存器用于存储返回值,它也用于做其他事情

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

您可以使用-S选项生成汇编代码,并查看EAX在“ret”指令之前发生的情况。

来自C标准:

从函数末尾流出相当于返回,而不返回 价值这将导致返回值时出现未定义的行为 功能

您的情况与此相同:

int factorial(int x){ return (x>1) ? (x * factorial(x-1)) : 1;}
它在我的机器上打印2。
这取决于时间和体系结构。返回值是最后一次表达式计算的结果,存储在eax寄存器中。

这甚至不应编译。请发布一些编译过的东西。@nvoigt,在我看来应该是这样的(但MSVC不会IIRC)。不管怎样,未定义的行为意味着它似乎可以工作。@chris我总是使用WarningAsErrors编译,你是对的,这是“唯一”警告。欢迎来到未定义的奇妙世界behaviour@Dgrin91,调用自身后不会返回任何内容。这不是如何生成阶乘函数的问题,这是一个为什么这个实现是“有效的”的问题。德格林欢呼道:)现在,如果我们能让每个人都像你一样积极地批评。
int factorial(int x){ return (x>1) ? (x * factorial(x-1)) : 1;}
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;
}