#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}返回正确的结果。
答案 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(将被隐式转换/转换),而不是错误,但不优雅。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寄存器中。