How exactly does tail recursion work? - c

I almost understand how tail recursion works and the difference between it and a normal recursion. I only don't understand why it doesn't require stack to remember its return address.
// tail recursion
int fac_times (int n, int acc) {
if (n == 0) return acc;
else return fac_times(n - 1, acc * n);
}
int factorial (int n) {
return fac_times (n, 1);
}
// normal recursion
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial(n - 1);
}
There is nothing to do after calling a function itself in a tail recursion function but it doesn't make sense for me.

The compiler is simply able to transform this
int fac_times (int n, int acc) {
if (n == 0) return acc;
else return fac_times(n - 1, acc * n);
}
into something like this:
int fac_times (int n, int acc) {
label:
if (n == 0) return acc;
acc *= n--;
goto label;
}

You ask why "it doesn't require stack to remember its return address".
I would like to turn this around. It does use the stack to remember the return address. The trick is that the function in which the tail recursion occurs has its own return address on the stack, and when it jumps to the called function, it will treat this as it's own return address.
Concretely, without tail call optimization:
f: ...
CALL g
RET
g:
...
RET
In this case, when g is called, the stack will look like:
SP -> Return address of "g"
Return address of "f"
On the other hand, with tail call optimization:
f: ...
JUMP g
g:
...
RET
In this case, when g is called, the stack will look like:
SP -> Return address of "f"
Clearly, when g returns, it will return to the location where f was called from.
EDIT: The example above use the case where one function calls another function. The mechanism is identical when the function calls itself.

Tail recursion can usually be transformed into a loop by the compiler, especially when accumulators are used.
// tail recursion
int fac_times (int n, int acc = 1) {
if (n == 0) return acc;
else return fac_times(n - 1, acc * n);
}
would compile to something like
// accumulator
int fac_times (int n) {
int acc = 1;
while (n > 0) {
acc *= n;
n -= 1;
}
return acc;
}

There are two elements that must be present in a recursive function:
The recursive call
A place to keep count of the return values.
A "regular" recursive function keeps (2) in the stack frame.
The return values in regular recursive function are composed of two types of values:
Other return values
Result of the owns function computation
Let's look at your example:
int factorial (int n) {
if (n == 0) return 1;
else return n * factorial(n - 1);
}
The frame f(5) "stores" the result of it's own computation (5) and the value of f(4), for example. If i call factorial(5), just before the stack calls begin to collapse, i have:
[Stack_f(5): return 5 * [Stack_f(4): 4 * [Stack_f(3): 3 * ... [1[1]]
Notice that each stack stores, besides the values i mentioned, the whole scope of the function. So, the memory usage for a recursive function f is O(x), where x is the number of recursive calls i have to made. So, if i needb 1kb of RAM to calculate factorial(1) or factorial(2), i need ~100k to calculate factorial(100), and so on.
A Tail Recursive function put (2) in it's arguments.
In a Tail Recursion, i pass the result of the partial calculations in each recursive frame to the next one using parameters. Let's see our factorial example, Tail Recursive:
int factorial (int n) {
int helper(int num, int accumulated)
{
if num == 0 return accumulated
else return helper(num - 1, accumulated*num)
}
return helper(n, 1)
}
Let's look at it's frames in factorial(4):
[Stack f(4, 5): Stack f(3, 20): [Stack f(2,60): [Stack f(1, 120): 120]]]]
See the differences? In "regular" recursive calls the return functions recursively compose the final value. In Tail Recursion they only reference the base case (last one evaluated). We call accumulator the argument that keeps track of the older values.
Recursion Templates
The regular recursive function go as follows:
type regular(n)
base_case
computation
return (result of computation) combined with (regular(n towards base case))
To transform it in a Tail recursion we:
Introduce a helper function that carries the accumulator
run the helper function inside the main function, with the accumulator set to the base case.
Look:
type tail(n):
type helper(n, accumulator):
if n == base case
return accumulator
computation
accumulator = computation combined with accumulator
return helper(n towards base case, accumulator)
helper(n, base case)
See the difference?
Tail Call optimization
Since no state is being stored on the Non-Border-Cases of the Tail Call stacks, they aren't so important. Some languages/interpreters then substitute the old stack with the new one. So, with no stack frames constraining the number of calls, the Tail Calls behave just like a for-loop in these cases.
It's up to your compiler to optimize it, or no.

Here is a simple example that shows how recursive functions work:
long f (long n)
{
if (n == 0) // have we reached the bottom of the ocean ?
return 0;
// code executed in the descendence
return f(n-1) + 1; // recurrence
// code executed in the ascendence
}
Tail recursion is a simple recursive function, where recurrence is done at the end of the function, thus no code is done in ascendence, which helps most compilers of high-level programming languages to do what is known as Tail Recursion Optimization, also has a more complex optimization known as the Tail recursion modulo

The recursive function is a function which calls by itself
It allows programmers to write efficient programs using a minimal amount of code.
The downside is that they can cause infinite loops and other unexpected results if not written properly.
I will explain both Simple Recursive function and Tail Recursive function
In order to write a Simple recursive function
The first point to consider is when should you decide on coming out
of the loop which is the if loop
The second is what process to do if we are our own function
From the given example:
public static int fact(int n){
if(n <=1)
return 1;
else
return n * fact(n-1);
}
From the above example
if(n <=1)
return 1;
Is the deciding factor when to exit the loop
else
return n * fact(n-1);
Is the actual processing to be done
Let me the break the task one by one for easy understanding.
Let us see what happens internally if I run fact(4)
Substituting n=4
public static int fact(4){
if(4 <=1)
return 1;
else
return 4 * fact(4-1);
}
If loop fails so it goes to else loop
so it returns 4 * fact(3)
In stack memory, we have 4 * fact(3)
Substituting n=3
public static int fact(3){
if(3 <=1)
return 1;
else
return 3 * fact(3-1);
}
If loop fails so it goes to else loop
so it returns 3 * fact(2)
Remember we called ```4 * fact(3)``
The output for fact(3) = 3 * fact(2)
So far the stack has 4 * fact(3) = 4 * 3 * fact(2)
In stack memory, we have 4 * 3 * fact(2)
Substituting n=2
public static int fact(2){
if(2 <=1)
return 1;
else
return 2 * fact(2-1);
}
If loop fails so it goes to else loop
so it returns 2 * fact(1)
Remember we called 4 * 3 * fact(2)
The output for fact(2) = 2 * fact(1)
So far the stack has 4 * 3 * fact(2) = 4 * 3 * 2 * fact(1)
In stack memory, we have 4 * 3 * 2 * fact(1)
Substituting n=1
public static int fact(1){
if(1 <=1)
return 1;
else
return 1 * fact(1-1);
}
If loop is true
so it returns 1
Remember we called 4 * 3 * 2 * fact(1)
The output for fact(1) = 1
So far the stack has 4 * 3 * 2 * fact(1) = 4 * 3 * 2 * 1
Finally, the result of fact(4) = 4 * 3 * 2 * 1 = 24
The Tail Recursion would be
public static int fact(x, running_total=1) {
if (x==1) {
return running_total;
} else {
return fact(x-1, running_total*x);
}
}
Substituting n=4
public static int fact(4, running_total=1) {
if (x==1) {
return running_total;
} else {
return fact(4-1, running_total*4);
}
}
If loop fails so it goes to else loop
so it returns fact(3, 4)
In stack memory, we have fact(3, 4)
Substituting n=3
public static int fact(3, running_total=4) {
if (x==1) {
return running_total;
} else {
return fact(3-1, 4*3);
}
}
If loop fails so it goes to else loop
so it returns fact(2, 12)
In stack memory, we have fact(2, 12)
Substituting n=2
public static int fact(2, running_total=12) {
if (x==1) {
return running_total;
} else {
return fact(2-1, 12*2);
}
}
If loop fails so it goes to else loop
so it returns fact(1, 24)
In stack memory, we have fact(1, 24)
Substituting n=1
public static int fact(1, running_total=24) {
if (x==1) {
return running_total;
} else {
return fact(1-1, 24*1);
}
}
If loop is true
so it returns running_total
The output for running_total = 24
Finally, the result of fact(4,1) = 24

My answer is more of a guess, because recursion is something relating to internal implementation.
In tail recursion, the recursive function is called at the end of the same function. Probably compiler can optimize in below way:
Let the ongoing function wind up (i.e. used stack is recalled)
Store the variables which are going to be used as arguments to the function in a temporary storage
After this, call the function again with the temporarily stored argument
As you can see, we are winding up the original function before the next iteration of the same function, so we are not actually "using" the stack.
But I believe if there are destructors to be called inside the function then this optimization may not apply.

Compiler is enough intelligent to understand tail recursion.In case, while returning back from a recursive call,there is no pending operation and recursive call is the last statement, fall under the category of tail recursion.
Compiler basically performs tail recursion optimization, removing stack implementation.Consider below code.
void tail(int i) {
if(i<=0) return;
else {
system.out.print(i+"");
tail(i-1);
}
}
After performing optimization , the above code is converted into below one.
void tail(int i) {
blockToJump:{
if(i<=0) return;
else {
system.out.print(i+"");
i=i-1;
continue blockToJump; //jump to the bolckToJump
}
}
}
This is how compiler does Tail Recursion Optimization.

Related

Where do recursive functions end?

#include <stdio.h>
int factorial(int n);
void main()
{
int n;
printf("Enter your number : " );
scanf("%d",&n);
if(n <= 1)
{
printf("The factorial of the number n is ",n);
}
else
{
int res = factorial(n);
printf("The result is %d\n",res);
}
}
int factorial(int n)
{
if(n <= 1)
return 1;
return n * factorial(n-1);
}
I'm doing a recursive function concept for the first time and i pretty much got like a 65% grasp on the concept of recursion. In the above program i have written a factorial recursion function and it goes normally well and i get the output but i'm trying to think where the recursion ends
Like for example i have gave an input of 5 :
The result is 120
but the main thing i wanted is why it doesn't continue after 0, if n <= 1(given if n = 0,-1...and so on during recursion) and then it should keep on returning "1" and multiplying with the recursion function(the factorial function being called inside the "factorial" function).In conclusion I really have no idea where the recursion ends...can you please clear it up.
Lets say you have call factorial(3), then the call-chain will be something like this:
factorial(3) // Initial call
factorial(2);
factorial(1);
return 1; // No more recursion
return 2 * 1; // 1 is the result of factorial(1)
return 3 * 2; // 2 is the result of factorial(2)
The result of factorial(3) will be 6 (3 * (2 * 1)).
In conclusion I really have no idea where the recursion ends..
It ends at the return 1; statement:
int factorial(int n)
{
if(n <= 1)
return 1; <---- Here
return n * factorial(n-1);
}
Maybe it's more clear if you wrote it like:
int factorial(int n)
{
if(n <= 1)
{
// No more recursive calls - just return 1
return 1;
}
else
{
// Do recursive call with decremented argument
return n * factorial(n-1);
}
}
So the code keeps doing recursive calls until n becomes 1. Then it returns 1 to the previous recursive call which returns 2 (2 * 1) to the previous recursive call which returns 6 (3 * 2) to the previous recursive call which returns 24 (4 * 6) .... and so on.
So the final result is calculated like:
1 * 2 * 3 * 4 * ...
\---/
2 * 3
\-------/
6 * 4
\-----------/
24
From Recursion:
In mathematics and computer science, a class of objects or methods exhibits recursive behavior when it can be defined by two properties:
A simple base case (or cases) — a terminating scenario that does not use recursion to produce an answer.
A recursive step — a set of rules that reduces all successive cases toward the base case.
So, terminating scenario('s)/condition('s) is one of property of recursion and it's where the recursion ends.
In context of your program:
Your program is finding the factorial of a given number n.
The factorial of a non-negative integer n is the product of all positive integers less than or equal to n:
n ! = n * ( n − 1 ) * ( n − 2 ) * ( n − 3 ) * ..... * 3 * 2 * 1
which is equivalent to
n ! = n * ( n - 1 ) !
that means, when writing program to calculate the factorial of a number n, we have to calculate the product of all positive integers and stop when reached to 1, which is the terminating condition.
In factorial() function:
int factorial(int n)
{
if(n <= 1)
return 1;
return n * factorial(n-1);
}
The condition if(n <= 1) is the terminating condition for recursive function finding the factorial of n and its where the recursive function factorial() ends.
Additional:
In your program, you are missing the format specifier in this
printf() statement:
printf("The factorial of the number n is ",n);
it should be
printf("The factorial of the number n is %d\n",n);
^^
Note that, 0! is 1 and, after making above change, your program
will give output as 0 when user give input number 0 which is
wrong.
May you should write function to calculate factorial of given positive number n like this:
unsigned int factorial(unsigned int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
and add a check on user input before calling factorial(). This will take care of 0! as well.
Using void as return type of main function is not as per
standards. The return type of main function should be int.
To understand simple recursive code, it helps a lot to draw a diagram (recursive trace). I will draw it in paint, but it's even better to do it on paper. Let's say we are calling factorial(3).
Write down the call of the function. (In the beginning, it's factorial(3))
Ask yourself: "Is the exit condition satisfied?" (In your case the condition is if(n <= 1))
If the answer is yes, check what gets returned and write it under the previous function call, then go to the next step. You have return 1; so 1 gets returned.
If the answer is no, check what gets returned and write it under the previous function call. You have return n*factorial(n-1); so the first time the return value will be 3*factorial(3-1), which is equal to 3*factorial(2). Now go back to step 1) with the new function call and repeat the process until the condition is satisfied. The call here is factorial(2). You can also connect the function calls with arrows to make the diagram more organized.
This is how the diagram should look like when your condition is satisfied:
You now go from the bottom upwards:Write down the value of the very bottom function call, and repeat for every function call above that. In your case, you first write the value of factorial(1), which is 1, then you move up, and you see that factorial(2) is equal to 2*factorial(1). And because you know that factorial(1) is equal to 1, you also know that
factorial(2) is equal to 2.
You can connect the function calls upwards to make the diagram more organized.
You are done. The diagram should look something like this:
With this diagram, we know exactly when the recursion stops - when factorial(1) is called. We also know the end result, which is 6.

tried a example from a c tutorial site kinda got it wrong

I was learning about recursion in C from https://www.tutorialspoint.com/cprogramming/c_recursion.htm and I tried the number factorial example.
#include <stdio.h>
int fact(int i) {
if (i <= 1) {
return 1;
}
return fact(i - 1);
}
int main() {
int i = 3;
printf("numb = %d", fact(i));
return 0;
}
After I executed the code it printed 1. I reviewed the code and found that I forgot to multiply var i with fact(i - 1) at the end of the function. I fixed it and got the correct factorial, but why is fact(3 - 1) equal to 1?
Edit
I had a very shallow understanding of recursion when i posted this question,i thought fact(i-1) would just execute once and didn't get the meaning of calling the function again in the tutorial and i didn't understand it at first when i read the busybee's answer i think i get it now fact(3-1) called fact(2-1) value of var i is now 1 and it satisfied the if condition and returned 1. Another question in the correct version where i multiply var i with fact(i-1) when i change return 1 to return 2 why does it return 12, from the pattern of return 1 and return 2 it seem to multiply 6 result of the function fact with the number in return why? i admit i did no research on what return does and just kinda went with the flow.
To compute the factorial recursively, i must be a positive integer. So that either the value of i is 0 or 1 the factorial will be 1.
If not, then call the recursive factorial algorithm with (i - 1) then multiply the result by i and return that value as shown:
#include <stdio.h>
int fact(int i)
{
if (i ==1)
return 1;
return fact(i - 1) * i; // You forgot to multiply i here
}
int main(void)
{
int i = 3;
printf("Number = %d", fact(i)); // Displaying the factorial of 3
return 0;
}
fact(3 - 1) returns 1 in your first and erroneous version, because it called fact() with i with 2.
This is not less or equal to 1, so fact() is called with 2 - 1. Now this is less or equal to 1, and 1 is returned.
This result is unchanged returned again, and finally once more returned to main().
As a list:
main() calls fact(3).
fact(3) calls fact(2), because its i is 3 and so greater than 1.
fact(2) calls fact(1), because its i is 2 and so greater than 1.
fact(1) returns 1 to fact(2), because its i is less or equal to 1.
fact(2) returns the 1 returned from fact(1) unchanged to fact(3).
fact(3) returns the 1 returned from fact(2) unchanged to main().
main() prints the 1 returned from fact(3).
Edit:
When you're in doubt how your functions are called and what they do, use a debugger (best approach) or insert some printf() (poor man's debugging, but quite easy), like this:
int fact(int i) {
printf("fact(%d) begins ...\n", i);
if (i <= 1) {
printf("... fact(%d) returns 1 because of %d <= 1\n", i, i);
return 1;
}
#if 1 // just temporarily
printf("... fact(%d) calls fact(%d)\n", i, i - 1);
int r = fact(i - 1);
printf("... fact(%d) returns %d\n", i, r);
return r;
#else
return fact(i - 1);
#endif
}
Edit 2:
You might have missed some important things in the lesson on recursive functions.
Each function has its own set of parameters and local variables.
In general, a recursively called function does not have any insight in the local variables or parameters of the calling function.
A recursively called function returns to the calling function. (Some compilers might optimize a "tail call" into a "tail jump", though.)

Tail recursion call (C primer plus book example)

In the C Primer Plus (6th edition), it defines the tail recursion concept
in this manner:
In the simplest form of recursion, the recursive call is at the end of the function, just before the return statement. This is called tail recursion, or end recursion, because the recursive call comes at the end. Tail recursion is the simplest form because it acts like a loop.
And it gives an example of calculating the factorial in a tail recursive manner:
long rfact(int n) {
long ans;
if (n > 0)
ans = n * rfact(n - 1);
else
ans = 1;
return ans;
}
It also makes a side note, which is not true in my opinion:
Note that although the recursive call to rfact() is not the last line in the function, it is the last statement executed when n > 0, so it is tail recursion.
One can clearly see that the last statement is n * rfact(n - 1) which, if you recursively expand, it will lead to a chain of deferred multiplications. The process is recursive in nature, so the implementation cannot be tail recursive as described here.
The example is misleading. What is your opinion?
As far a good C programming book goes, I used the C programming language.
You are correct in saying this is not tail recursion. The typical tail recursion example for a factorial is:
int factorial(int x) {
return tailfactorial(x, 1);
}
int tailfactorial(int x, int multiplier) {
if (x <= 0) {
return multiplier;
}
return tailfactorial(x - 1, x * multiplier);
}
I imagine that your book did not explain the purpose for tail recursion. Tail recursion is used in order to not increase the "stack depth". The compiler can replace the recursive call with a "goto" command which does not increase the stack depth. This compiler modification is only made when the value of the recursion is returned directly. You will notice in your example that this is not the case.
The given definition and example both are misleading. The definition of tail recursion is:
A function call is said to be tail recursive if there is nothing to do after the function returns except return its value.
It is not not necessary that recursive call should be just before the return statement or last statement of the function. See an example:
function foo(data) {
a(data);
return b(data);
}
In this case a is just before the return statement but b is in tail position.
function bar(data) {
if ( a(data) ) {
return b(data);
}
return c(data);
}
In this example, both b and c are in tail position though b is not at the end of the function bar.
In your given example, the last thing function is performing before return is multiplication
ans = n * rfact(n - 1);
Therefore, its not a tail recursive function.
Am example of tail recursive function is
factorial1(n, accumulator) {
if (n == 0) return accumulator;
return factorial1(n - 1, n * accumulator); // The last thing, before return, performed
// by factorial1 is to call itself.
}
factorial(n) {
return factorial1(n, 1);
}
which may be optimize by compiler to
factorial1(n, accumulator) {
while (n != 0) {
accumulator *= n;
n -= 1;
}
return accumulator;
}

Recursive function to loop and stack

It's well known all recursive functions can be written using just a single loop and a stack. Although this conversion can be criticized to be ugly or less readable, its main use is obviously to avoid smashing the heap.
There are natural ways to convert simple recursive functions into loops. For instance, take the simple tail-recursion elimination using an accumulator. So far, I have not seen yet a definitive answer for this question.
At least to me, sometimes it seems black magic to convert such recursive functions into loops provided a stack. For instance, think of writing a non-recursive version for
f(n) = n, if n <= 1
f(n) = f(n-1) + f(n-2) + 1, if n > 1
The very point underlying this question is:
Is there a lucid, general method to convert a recursive function into a loop + stack?
Feasibility (100%):
From here, we know that any recursive function can be converted to iterate (into a loop) but you need to use a stack yourself to keep the state.
How to do this (generally):
You can check out the article How to replace recursive functions using stack and while-loop to avoid the stack-overflow, which gives examples and steps (10 steps/rules) on how to convert recursive functions to stack and while-loop. See the following part for real example.
Example:
Take the following recursive function as an example:
// Recursive Function "First rule" example
int SomeFunc(int n, int &retIdx)
{
...
if(n>0)
{
int test = SomeFunc(n-1, retIdx);
test--;
...
return test;
}
...
return 0;
}
After applying the 10 rules/steps introduced in the article (details shown in comments), you will get:
// Conversion to Iterative Function
int SomeFuncLoop(int n, int &retIdx)
{
// (First rule)
struct SnapShotStruct {
int n; // - parameter input
int test; // - local variable that will be used
// after returning from the function call
// - retIdx can be ignored since it is a reference.
int stage; // - Since there is process needed to be done
// after recursive call. (Sixth rule)
};
// (Second rule)
int retVal = 0; // initialize with default returning value
// (Third rule)
stack<SnapShotStruct> snapshotStack;
// (Fourth rule)
SnapShotStruct currentSnapshot;
currentSnapshot.n= n; // set the value as parameter value
currentSnapshot.test=0; // set the value as default value
currentSnapshot.stage=0; // set the value as initial stage
snapshotStack.push(currentSnapshot);
// (Fifth rule)
while(!snapshotStack.empty())
{
currentSnapshot=snapshotStack.top();
snapshotStack.pop();
// (Sixth rule)
switch( currentSnapshot.stage)
{
case 0:
// (Seventh rule)
if( currentSnapshot.n>0 )
{
// (Tenth rule)
currentSnapshot.stage = 1; // - current snapshot need to process after
// returning from the recursive call
snapshotStack.push(currentSnapshot); // - this MUST pushed into stack before
// new snapshot!
// Create a new snapshot for calling itself
SnapShotStruct newSnapshot;
newSnapshot.n= currentSnapshot.n-1; // - give parameter as parameter given
// when calling itself
// ( SomeFunc(n-1, retIdx) )
newSnapshot.test=0; // - set the value as initial value
newSnapshot.stage=0; // - since it will start from the
// beginning of the function,
// give the initial stage
snapshotStack.push(newSnapshot);
continue;
}
...
// (Eighth rule)
retVal = 0 ;
// (Ninth rule)
continue;
break;
case 1:
// (Seventh rule)
currentSnapshot.test = retVal;
currentSnapshot.test--;
...
// (Eighth rule)
retVal = currentSnapshot.test;
// (Ninth rule)
continue;
break;
}
}
// (Second rule)
return retVal;
}
BTW, the above article is the Prize winner in Competition <Best C++ article of July 2012> of CodeProject, so it should be trust-able. :)
Yes, but the solution won't be much better than the recursive one except maybe reduce the chance for a stack overflow.
By looking at the sequence, which is similar to the Fibonacci sequence except you add 1 to the result for every round except n = (0,1), you see a pattern.
0 1 2 4 7 12 20
\ \___ ...\____
0+1+1 1+2+1 7+12+1
Since the whole generation is dependent on the two previous numbers you can have two variables in a loop representing that and you don't need to have a stack at all.
//intentional generic algol dialect
int modfib (int n)
{
if( n <= 1 )
return n;
n = n - 2;
int a=2;
int b=4;
int tmp;
while( n-- > 0 )
{
tmp=a;
a=b;
b = tmp + b +1;
}
return a;
}
Until compilers know to do this we still need humans to optimize code.

Can Recursion be named as a simple function call?

Please consider an Recursive function :
1) int calc(int num)
{
2) sum=sum+num;//sum is a global variable
3) num--;
4) if(num==0)
5) return sum;
6) calc(num);
}
It calculates the sum of an integer .
My teacher told me it's not recursion, but a simple function call, because you need to pass
num-- as an argument and return calc(num--) .
I was shocked, as I knew only one thing when a function call itself, its recursion.
She also gave the reason, that line no. 2 and 3 is stored extra in stack memory.
I have no idea what she was referring to.So after going through stack storage thingy:
Here, I noticed that the function arguments passed are in a recursive way, like n-- in my function.
So that they can be linked to the next function call.
For just this sake, can we term it a simple function call instead of recursion?
The teacher has something quite specific in mind even though what you presented is, technically, recursive. Another form which wouldn't depend upon the global would look something like this:
int calc(int num) // Assume this is valid for non-negative numbers
// In that case, type "unsigned int" would be more appropriate
{
if ( num < 0 )
return -1; // Consider this an error; won't happen in recursive case
if ( num == 0 )
return 0;
return num + calc(num-1);
}
You are correct, recursion is a function that calls itself. PERIOD. There are other points worth separately discussing about global variables, and other good programming practices, but whether you implement the decrement operator in the line of code where you call the function recursively or prior to that point, you are still making a recursive call.
It looks like you're trying to calculate, for a given num, the sum of 0 to num. The calc function really just needs one argument, num, and can then call a helper function calc_num which takes the current number and the running sum:
int calc( int num ) {
return calc_help( num, 0 );
}
Then, calc_help, given a current number, and the sum so far, checks whether num is less than or equal to zero. If it is, then the current running sum is the final sum and can be returned. Otherwise, a recursive call to calc_help is made. The current number for it will be one less than num (so that we're calling calc_help with successively smaller first arguments, getting closer and closer to the case where num <= 0), and the current sum will be sum plus the current number:
int calc_help ( int num, int sum ) {
return num <= 0 ? sum : calc_help( num-1, sum+num );
}
In a language (like Scheme) that performs tail call optimization, this is essentially the following loop. Some C/C++ compilers do perform tail call optimization (e.g., according to Tail recursion in gcc/g++, GCC will optimize tail calls when -O2 is specified), so this isn't entirely a moot point.
int calc( int num ) {
int sum = 0;
while ( num > 0 ) {
sum = sum+num;
num = num-1;
}
return sum;
}
or (if you want to be a bit more obscure):
int calc( int num ) {
int sum = 0;
for ( ; num <= 0; sum+=num, num-- );
return sum;
}
The more naïve recursive implementation that performs the addition of after the recursive call, i.e.,
int calc( int num ) {
return num <= 0 ? num : num + calc( num-1 );
}
can't be optimized in this way.

Resources