tags:

views:

569

answers:

6

I was playing around with recursion and did this simple function. I was assuming that it would print out 9-0 to stdout, but, it prints 0-9. I can't see how that happens at all.

int main()
{
        rec(10);
        return 0;
}

int rec(int n){
        if(n > 0)
                printf("%d\n", rec(n -1));
        return n;
}
+17  A: 

The rec function on the printf line is evaluated before the printf itself. Thus the deepest instance of the rec function is printed first.

tloflin
I guess that I was confused by the fact that the printf is also part of the rec function. Thanks for the explanation, I just started with this.
Fred
No problem, glad to help. Just remember that evaluation of functions always goes inside-out: the parameters are evaluated before the function.
tloflin
+10  A: 

Think of it like this.

rec(10)
rec(9)
rec(8)
rec(7)
rec(6)
rec(5)
rec(4)
rec(3)
rec(2)
rec(1)
rec(0)

Start Unwinding

printf("%d\n", 0);
printf("%d\n", 1);
printf("%d\n", 2);
printf("%d\n", 3);
printf("%d\n", 4);
printf("%d\n", 5);
printf("%d\n", 6);
printf("%d\n", 7);
printf("%d\n", 8);
printf("%d\n", 9);
ChaosPandion
Thanks you, that is a good explanation. I'll take a look in the debugger as well, as was suggested.
Fred
+8  A: 

As Michael Burr says in the comments, if you want to see what's going on, compile with debugging symbols enabled, like this:

gcc -o test -g test.c

Then run with gdb like so.

gdb test

Then, to start things going, type

start

Which breaks at the first call in the main function. Type

step

to get to the next line in the code, and from then on, just press enter to keep repeating the last command. If you're happy, type continue to stop stepping through. You'll see the values and evaluated lines at each stage which'll confirm the above answers.

Hope that provides some useful info.

Ninefingers
Another useful GDB command is `list`, which shows you some lines from your source file.
Thomas Matthews
@Thomas feel free to edit in anything in you think is useful!
Ninefingers
Thanks, that's great. I don't have too much experience with gdb, so this is perfect. I'll give it a try.
Fred
@Fred no problems. I've found it's actually really easy even though once upon a time I attributed its usage to demi-god-like status. I actually find it more useful than the Visual Studio debugger was when I coded on Windows. You might also want to check out valgrind if you're learning on Linux - it checks for memory leaks (i.e. correct usage of calloc/free). Very useful for spotting bugs before you pull your hair out.
Ninefingers
You answer spawned this, which I submit for your review: http://stackoverflow.com/questions/2588853/the-community-driven-gdb-primer
fbrereto
@fbrereto thanks, I'll get to it.
Ninefingers
+10  A: 

Let's rewrite your code like this:

int rec(int n){
        if(n > 0)
        {
                int retval = rec(n -1);
                printf("%d\n", retval);
        }
        return n;
}

Does it make it clear why 0 printed first before 9?

Lie Ryan
I usually nest functions like that if I intend to print them, It's the fact that the printf is also part of the rec function that got me confused I think. Thanks
Fred
+3  A: 

Because you're creating 9 ambients 9 > 8 > 7 > 6 > 5 > 4> 3 > 2 > 1 > 0, now these ambients are treated the same this would a(b(c(d(e(f(g())))))), going from the deepest one to the first one.

Remember that when you do this printf("%d",n(m)); you're actually not printing anything, you're saying "print the result of n(m)" then when it tries to resolve n(m) you're calling another print and saying once again "resolve n(m-1)".

Now, when you reach n(0) it will return 0 to be printed by the last call of printf, therefore it prints 0 then 1 .. 9.

Ben
Thanks, that is very useful! I haven't really give recursion that much though before, and just decided to start to make some experiments with it. That makes sense.
Fred
A: 
int main()
{
        rec(10);
        return 0;
}

int rec(int n){
        if(n > 0)
                printf("%d\n", rec(n -1));
        return n;
}

In general, consider some piece of code. We say there is a direct relation between iterative and recursive solutions such that any solution can be written iteratively and vise versa. However, in some cases it is seen to be easier to express an algorithm recursively (eg. Tower of Hanoi.) In the case of the code above the equivalent would be the for loop construct.

This can be implemented as a function as follows:

void _for(int i, int n)
{
    if( i >= n ) return; // TERMINAL<br />
    // some expression (ie. printf("%d\n",i);)<br />
    _for(i+1,n) // RECURSION<br />
}

Note, this can be extended using function pointers.

Might want to check out the markdown editor FAQ. http://stackoverflow.com/editing-help
ChaosPandion