Reformatting and adding some line numbers to assist in the discussion below
Code:
/* 1 */ int leaf(int f)
/* 2 */ {
/* 3 */ int result;
/* 4 */ result = f-1;
/* 5 */ if (f<5)
/* 6 */ return result;
/* 7 */ leaf(result);
/* 8 */}
As written, this should invoke undefined behavior per section 6.9.1, paragraph 12:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
The first time leaf is called from printf, the value of the parameter f is 5. (f < 5) evaluates to false, so execution skips to line 7 and leaf is called again. This time, the value of the parameter f is 4. (f < 5) evaluates to true, so line 6 is executed, returning the value 3. Execution picks up at line 8, which is the closing }.
A graphical representation of the call tree should help:
Code:
printf("%d", leaf(5));
leaf(5) // call from printf
{
int result;
result = 4;
if (5 < 5)
leaf(result);
leaf(4) // call from leaf(5)
{
int result;
result = 3;
if (4 < 5)
return 3; // return to leaf(5)
} // return to printf
Since execution has reached the closing } and the value of the function call is being used by the caller, the resulting behavior is undefined.
Since the behavior is undefined, anything can happen at this point. You may get an output of 3. You may get an output of 4. You may get garbage. You may get no output at all.
The fix is easy. Instead of writing
Code:
if (f < 5)
return result;
leaf(result);
use
Code:
if (f < 5)
return result;
return leaf(result);
or
Code:
if (f < 5)
return result;
else
return leaf(result);