2
#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;
}

This function is to compute the factorial of an integer number. In the branch of x>1,there is no return value for function Fun. So this function should not return correct answer.

But when fun(4) or some other examples are tested, the right answers are got unexpectedly. Why?

The assembly code of this function is(call 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

May be this is the reason: The value of sum is saved in register eax, and the return value is saved in eax too, so Funreturn the correct result.

tenos
  • 909
  • 1
  • 9
  • 16

6 Answers6

1

When your program pass in the if condition, no return statement finish the function. The number you got is the result of an undefined behavior.

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

    return x; // return something here
}
Yabada
  • 1,728
  • 1
  • 15
  • 36
1

Usually, EAX register is used to store return value, ad it is also used to do other stuff as well.

So whatever has been loaded to that register just before the function returns will be the return value, even if you don't intend to do so.

You can use the -S option to generate assembly code and see what happened to EAX right before the "ret" instruction.

Trangohan
  • 51
  • 1
0

As stated in the comment this is undefined behaviour. With g++ I get the following warning.

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

On Visual C++, the warning is promoted to an error by default

error C4716: 'Fun' : must return a value

When I disabled the warning and ran the resulting executable, Fun(4) gave me 1861810763.

So why might it work under g++? During compilation conditional statements are turned into tests and jumps (or gotos). The function has to return something, and the simplest possible code for the compiler to produce is along the following lines.

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

This is consistent with your disassembly.

Of course you can't rely on undefined behaviour, as illustrated by the behaviour in Visual C++. Many shops have a policy to treat warnings as errors for this reason (also as suggested in a comment).

Community
  • 1
  • 1
TooTone
  • 7,129
  • 5
  • 34
  • 60
0

Just remove else from your code:

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

    return sum;
}
Sergey K.
  • 24,894
  • 13
  • 106
  • 174
0

The code you have has a couple of errors:

  • you have an int being assigned the value 1.0 (which will be implicitly cast/converted), not an error as such but inelegant.
  • you have a return statement inside a conditionality, so you will only ever get a return when that if is true

If you fix issue with the return by removing the else, then all will be fine:)

As to why it works with 4 as an input, that is down to random chance/ some property of your environment as the code you have posted should be unable to function, as there will always be an instance, when calculating factorials for a positive int, where x = 1 and no return will be generated.

As an aside, here is a more concise/terse function: for so straightforward a function you might consider the ternary operator and use a function like:

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

this is the function I use for my factorials and have had on library for the last 30 or so years (since my C days) :)

GMasucci
  • 2,834
  • 22
  • 42
0

From the C standards:

Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.

Your situation is the same as this one:

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;
}

It prints 2 on my machine. This is calling convention and architecture dependent. The return value is the result of last expression evaluation, stored in the eax register.

jfly
  • 7,715
  • 3
  • 35
  • 65