The trick to understanding recursion is understanding the stack.
I'm at line 2 in a function called main
, all my local variables are stored in my stack frame:
+------------------+
| main() variables | The stack frame
+------------------+
I then call fib(3)
, so the computer pushes my current position (EIP) to the stack, then creates a new stack frame for fib and adds that on too. I can only ever access the top stack frame:
+------------------+
| fib() n = 5 | Top of stack (current frame)
+------------------+
| EIP: main @ 2,1 |
+------------------+
| main() variables | Bottom of stack
+------------------+
On line 4 of fib
, it calls fib
again, so the same happens again:
+------------------+
| fib() n = 4 | Top of stack
+------------------+
| EIP: fib @ 4,1 |
+------------------+
| fib() n = 5 |
+------------------+
| EIP: main @ 2,1 |
+------------------+
| main() variables | Bottom of stack
+------------------+
And it does this again and again as the function is recursively called. The stack grows until something returns, at which point, at line 2 of fib
, it returns 1. This pops the top stack frame and discards it, it then returns execution to the saved execution pointer and the program continues where it left off
+------------------+
| fib() n = 3 | Top of stack
+------------------+
... etc ...
+------------------+
| EIP: main @ 2,1 |
+------------------+
| main() variables | Bottom of stack
+------------------+
Eventually you end up back in the calling function (or you get a stack overflow as it grows too large). The key thing to remember is that each time the function is called, it gets a new stack frame containing all your local variables, and your previous position is saved. That's recursion.
The main problem is that in teaching people recursion, everyone always uses the Fibonacci sequence which means having two recursive function calls on one line. This is unnecessarily confusing, as I'm sure you'll agree!