问题
How is the value of I getting printed?
I know the recursion calls itself again and again. According to me, the function should return empty as the function is called before printing. How is the printf
working?
recur(int i)
{
if(i<0)
return 0;
recur(--i);
printf("%d",i);
recur(--i);
}
main()
{
recur(2);
}
The output of this program is
-1
0
1
-1
Can someone explain how is it working?
回答1:
To understand what happens, you have to understand how recursion works. Every recursive function requires a test condition to break the recursion and a recursive call. You have if (i < 0)
as your test condition and then your have two recursive calls with printf
between them.
So How Does This Work?
You can think of recursion and winding-up until the exit condition is triggered -- and then an unwinding as the recursive calls return. Let's see how this works here.
The Recursion
When you start with recur(2)
in main
, what path does the logic take to wind-up to the exit condition?
If you simplify the function and concentrate on what happens before your test condition is met, you get something similar to:
void recur (int i) {
if (i < 0)
return;
recur (--i);
/* comes after return */
}
Let's follow it through. On the first call, i = 2
so --1
pre decriment occurs making i = 1
, recur (1)
executes. Next call i = 0
, recur (0)
is called again. Finally, i = -1
, and the first recur(-1)
occurs, so if (i < 0)
executes and return
is called.
Now What? -- The Unwinding...
Look at the above shortened function. When you return
, you are returning from the last call to recur(--i)
so control is now passed to the next command after the first recur(-1)
(shown as /* comes after return */
above) So what are the next commands in the full function?
printf("%d\n", i);
recur (--i);
What was the value of i
when this first occured? (hint: -1
).
So printf
is called and then what comes next? Your second recur(--i)
. There i = -2
, the if (i < 0) return;
is triggered and you unwind out of the second recur(-2)
-- there is no command that follows and that function call is now complete.
Control now unwinds to within the previous call where i
is now 0
, the printf
is called and the second recur(--i)
is entered with i = -1
which simply hits return
again and you unwind one more level to where i = 1
returning again from the first recur(--i)
call, 1
is output.
The second recur(--i)
call is entered where after decrement i = 0
and you now recurse once more into the first where i = -1
again triggering return
which causes contol to pass to printf
with the final -1
printing.
You now recurse into the second recur(--i)
with i = -2
triggering return
and completing the function call and the recursion.
So if you go back through the control of your recursive function with two recursive calls and look at each time printf
was reached you have output -1, 0, 1, -1
.
Still Think Recursive Functions With Multiple Recursive Calls Are A Good Idea?
(they are if you are an Aspirin salesman -- otherwise, they are best avoided unless they are the only reasonable option you have)
The only way to get through something like this is to either (1) make friends with your debugger and single-step through your code keeping a scratch sheet of which call was entered when, or (2) copy and paste the function down the page tracking the state of the recursive call at each level and take it step-by-step.
Always a good learning experience, but if a procedural solution is available, the logic is much more straight-forward and you avoid the function call overhead of every recursive call. Recursive functions have their place, and there are some problems to which they provide very elegant solutions. But you have to be mindful of how many times the recursion will occur as you allocate a separate function stack and space for local variables with every call -- which can lead to StackOverflow.
回答2:
When you call recur(2);
, then at this point
recur(--i);
recur(1)
is called, and then when it reaches that point again, recur(0);
is called and then at that point again, recur(-1);
is called. The recur(-1);
call immediately returns because if(i<0) return 0;
.
The recur(0);
call, where i
is now -1
, then does the print, and returns (it does recur(--i);
again, but that's -2
at this point). Next, the recur(1)
call (where i
is 0
now) does its print, and the it also hits recur(1)
, which returns.
Finally, the original recur(2);
call (where i
is 1) does its print and calls another recur(0);
, which as we've seen, results in -1
being printed. This results in the output of -101-1
, or if you add a newline to each print, the output that you are seeing.
On a side note, I suggest writing your main function as
int main()
{
recur(2);
return 0; // return value of 0 indicates successful program execution
}
and change the signature of recur(int i)
to void recur(int i)
and its return 0;
to just return;
.
according to me the function should return empty as the function is called before printing. how the printf is working?
To sum it up, it's working because not all recursive calls are doing further recursive calls. They only do recursive calls under certain conditions, and if they don't do that recursive call, they finish at some point, allowing the function that called it to continue.
回答3:
The problem is that you are calling your function before you are printing out the value.
recur(int i)
{
if(i<0)
return 0;
recur(--i);
printf("%d",i);
recur(--i);
}
You are calling recur(2)
in your main
function the first if(i<0)
does not return 0 because i=2
. Then your function recur is called with the value 1 recur(1)
The if(i<0)
in this case does also not return 0 because i=1
than your function recur(0)
is called with 0.
The if(i<0)
does still not return 0 beacuse i=0
and your function is called with recur(-1)
.
Then you're if(i<0)
returns 0
beacuse i=-1
.
Now we start to print()
out the values we gave the function previously.
Which was print(-1)
because it was the last value that our function had.
Then we call recur again with recur(-2)
and the if returns 0.
Then we print(0)
because that was the second value we "entered" was 0.
Then we call recur with recur(-1)
and the if(i<0)
returns 0.
This goes on for the next values.
For future problems, I would recommend you to use a debugger. GDB debugger for example.
Here is a like to get started with gdb: GDB Start guid
I hope this helps you.
回答4:
ALSO CONSIDER
you are using the variable is as auto variable the value of auto variables is limited with the panathesis so the program will print the value of i available within the paranthesis at which the control flow currnetly resides
回答5:
When the function is called with an argument X >=
zero, you'll have these lines executed:
recur(X-1)
print X-1
recur(X-2)
return
When the function is called with an argument X <
zero, you'll only have this line executed:
return
Now if you write the function calls with some indentation for each call level you get:
recur(2)
recur(1)
recur(0)
recur(-1)
return
print -1
recur(-2)
return
return
print 0
recur(-1)
return
return
print 1
recur(0)
recur(-1)
return
print -1
recur(-2)
return
return
return
return
Removing everything except the print gives:
print -1
print 0
print 1
print -1
So the output is:
-1
0
1
-1
回答6:
Instead of doing recur(--i)
, please do recur(i-1)
With --i
it will actually decrease i
, and so in later printf
it will be visible (incorrectly).
For eg. if i
is 0
and you do recur(--i)
, it will decrease the actual value of i
to -1
and then call recur()
. And the printf
will print -1
later.
With recur(i-1)
, and i
as 0
it will be call with -1
as argument but the actual value of i
will not be changed.
来源:https://stackoverflow.com/questions/54361174/recursion-flow-in-c-language-and-how-the-output-is-printed