Click here to Skip to main content
15,888,020 members
Please Sign up or sign in to vote.
1.40/5 (2 votes)
See more:
C++
#include <stdio.h>
#include <stdlib.h>
int f(int);
int main()
{
    int n=12347,s=0;
    s=f(n);
    printf("S=%d\n",s);
    return 0;
}
int f(int a)
{
    int i,s=0,r;
    if(a==0)
    return s;
        r=a%10;
        s=r+s;
        f(a/10);
}
Posted
Updated 29-Jan-16 3:21am
v4
Comments
Tomas Takac 21-Jan-16 7:36am    
Does it compile? Because you are missing a return in f().
Anupkumar_vj 21-Jan-16 8:41am    
yes..it compiles on Codeblock compiler
Rahul VB 29-Jan-16 9:23am    
Yes it would compile giving a warning. In C# (Managed code), you would get an error.
phil.o 21-Jan-16 7:56am    
That's a perfect case for a debugging session.
Philippe Mori 29-Jan-16 21:45pm    
As other as pointed out, this is undefined behaviour... I serve almost no useful purpose to know what will happen in that case.

The reason is that not all pathes of your function f() return a value explicitly.

But there is a (hidden) value returned:
You are calling f() as last call in your code so that the return value from that function call is returned. Because the function is called iteratively until the parameter a is zero, the return value of the last call is zero. Then that value is passed back to each next upper call so that the final return value is always zero.

[EDIT]
To make it better understable. Your code behaves similar to:
return f(a/10);

Return values of integral type (like int) are passed in a specific platform dependant register. When not having a return statement, the register contains still the return value from the last call.

If you would have called another function as last call, the value would be different:
C++
int f(int a)
{
    /* ... */
    f(a/10);
    printf("s=%d\n", s);
}

With the above, the return value of the printf() function is returned (the number of characters actually printed).
[/EDIT]
 
Share this answer
 
v2
Comments
Andreas Gieriet 29-Jan-16 10:14am    
The behavior is undefined, i.e. anything may happen. See also my solution #4.
Cheers
Andi
Jochen Arndt 29-Jan-16 10:23am    
You are right that it is undefined by the standard.

I just wanted to explain what happens here to answer the question "why is the output 0". While there might be compilers that behave different, most (if not all) will let the storage of the return value set by the deepest call untouched. See also my discussion at solution 3.
Andreas Gieriet 29-Jan-16 10:31am    
What if the last called function is a void function? E.g. the ARM Procedure Call Standard passes arguments under certain conditions in R0, R1, R2 and R3 and returns the value in R0. If the function is a void function, the last R0 assigned value would be the one passed to the last function and not any kind of return value.
It's far to dangerous to even "know" about this, I'd say, because it does not even hold always for one compiler.
Cheers
Andi
Jochen Arndt 29-Jan-16 10:45am    
Here the last call is a recursive call to the function itself. This is a very special case and my answer is only about that.

With my example of printf() the return value would be the value from within the initial (level 0) call because that is called last.

With a void function the return value would be undefined because it can be assumed that the return register (e.g. R0, EAX) has been used somewhere else.
Andreas Gieriet 29-Jan-16 11:21am    
We both know that this is broken code, and I wanted to highlight to the OP that due to that it's not worth to analyze *why*. This is not obvious in your answer - one might interpret your solution as intended behavior. That's all :-)
Cheers
Andi
Your code can do just about anything - in C when you fall off the end of a function with out an explicit return statement and then use the value that's returned it's undefined behaviour. Your implementation could set to just about anything and still be a valid program. The compiler would be perfectly legal if it just converted the entire function to return 0; for every code path or do something even weirder.

In reality you're probably getting whatever junk is left kicking around in whatever register is normally used to return integer values (usually AX/EAX/RAX on most compilers for x86 and amd64). You're probably "lucky" that the same register is used for an integer division immediately before. However I really wouldn't bank on that behaviour.
 
Share this answer
 
Comments
Jochen Arndt 22-Jan-16 3:45am    
You are right the behaviour is undefined by the C standard.

But in reality it is always zero because all compilers will not touch the return value register in this case:
- The last recursive call will return zero (set the register).
- The point where it continues after that return is the end of the function one level above. There is only the stack cleanup and an assembly return statement.
- This continues until the recursion finished.
So the content of th register before calling the recusrive function does not matter.
Aescleal 22-Jan-16 4:35am    
It's a bit daft to say that every compiler/OS/processor combination on the planet will return zero. Having used a compiler that tried executing nethack when it saw a #pragma I wouldn't put it past some witty compiler author to say "sod the world, I'm going to set all the volatile registers to random junk before I do an implicit return." I can even see a point at which that'd be useful if the junk was deterministic - it might help detect situations where someone's trying to use an undefined return value and not using -Wx.
Jochen Arndt 22-Jan-16 4:58am    
A compiler doing anything else would be daft. The return register is not a volatile register at this point. It can (and is) used for other purposes but once set with a return value must not be touched anymore. For this reason the cleanup code before return and upon return (at the calling site) will not change it (or save and restore).

However, there might be compilers that will explicitly set a return value (probably zero) when there is no return statement inside a function return path. But I don't know any C compiler doing this while this is for example the default with Basic.
Aescleal 22-Jan-16 7:29am    
The thing is there isn't a return value - there's no return statement. There's nothing telling the compiler "hands off!" on whatever mechanism it uses for returning values. There's nothing saying "propagate the value returned from the recursive call."

As a concrete example: If you have an architecture that uses a block of memory to hold parameters and return values there's nothing in that second branch of code that will update the caller's parameter/return block with the callee's return value. It'll end up with the same value you had before and the function essentially becomes:

int f( int a )
{
return a;
}

and you've got different output.
Jochen Arndt 22-Jan-16 7:54am    
Your second paragraph above nails it: The block (or register) is not changed. It is set with the deepest recursion execution and read out when returning from the initial call.

But your conclusion is wrong. It behaves here like:
 return f(a)
because f(a) is called as last instruction of the function.

The value of 'a' and how it is passed does not care because it is a parameter and not the return value. Even when for example the compiler moves 'a' to eax and passes that or pushes it onto the stack, the return value is not affected because when starting returning from the deepest call all parameters are out of scope.

Please don't take my commments to seriously. My goal was just to show that the behaviour is undefined by the standard but comprehensible and your assumption about the value of 'a' being in the return register (or used for division as mentioned in your solution) does not care here.
Why bother about this code at all?! Fix it!
The C++ standard is explicitly stating this as undefined behavior:

6.6.3:
[...] 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.[...]

1.3.24:
undefined behavior [...] Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results[...]

Cheers
Andi

PS: The respective section in the C Standard is 6.8.6.4: [...] A return statement without an expression shall only appear in a function whose return type is void.[...]
 
Share this answer
 
v2
Returns 0 because you explicitely set s=0 just before the return statement.
 
Share this answer
 
Comments
Afzaal Ahmad Zeeshan 21-Jan-16 8:47am    
Yes, but a is not zero. :-)
CPallini 21-Jan-16 11:56am    
You are wrong, the function does return only if a==0 holds.
Afzaal Ahmad Zeeshan 21-Jan-16 12:00pm    
But while calling, he is passing, 12347.
CPallini 21-Jan-16 12:14pm    
The function is recursive.
[no name] 29-Jan-16 10:19am    
But as has been pointed out on the last call of f(a / 10); it does not recurse but falls through with no return value.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900