Reputation:
I usually program in java and recently watching some c codes. I came up across this program and I don't know how this pointer thing is working. I know pointer stores the address and all but couldn't make it through the program. Please tell how is the output coming as 8 ?
#include <stdio.h>
int fun(int n, int * f_p) {
int t, f;
if (n <= 1) {
*f_p = 1;
return 1;
}
t = fun(n - 1, f_p);
f = t + *f_p;
*f_p = t;
return f;
}
int main() {
int x = 15;
printf("%d\n", fun(5, &x));
return 0;
}
Upvotes: 3
Views: 11069
Reputation: 320777
What you have here is a recursive function that calculates the i-th element of a Fibonacci sequence (indexing from 0
). Each recursive iteration returns two values: the i-th Fibonacci number and the (i-1)-th (previous) Fibonacci number. Since a function in C can only return one value (well, unless you use a struct as return type), the other value - the previous Fibonacci number - is returned to the caller through a pointer parameter f_p
.
So, when you call fun(5, &x)
, the function will return 8
, which is the 5-th Fibonacci number, and it will also place 5
into x
, which is the previous (4-th) Fibonacci number.
Note that the initial value of x
does not matter. That 15
does not play any role in this program. Apparently it is there as a red herring.
If you know what a Fibonacci sequence is, you know that the next element of the sequence is the sum of the two previous elements. This is why the function is written to "return" two elements of the sequence to the caller. You might not care about that previous value in the top-level caller (i.e in main
), but the nested recursive calls do need it to calculate the next number. The rest is pretty straightforward.
Upvotes: 6
Reputation: 1981
As these things go, it's technically straightforward, but...stupid, in the sense that nobody should do things like this. It's a bad use of recursion and badly-written recursion, given the side effects.
The original call of fun(5, &x)
isn't going to trip the condition. So, it'll recurse four times (5-1, 4-1, 3-1, 2-1). That's your base condition, which has the effect of setting the pointed-to location (the original x
) to 1
and returning 1
.
Then we unroll the four calls, each time adding the returned value to the thing at the pointer and changing the thing at the pointer to be that sum.
In simple English, you're doubling one three times.
Edit: As pointed out, I misread the code as assigning f
to *f_p
rather than t
. That makes it a Fibonacci counter.
Upvotes: 1
Reputation: 470
Step by step:
f = t + *f_p
which is 1+1 -> f=2;
the variable pointed by f_p is set to t so x=1, returns f so it returns 2f = t + *f_p
which is 2+1 -> f=3;
the variable pointed by f_p is set to t so x=2, returns f so it returns 3f = t + *f_p
which is 3+2 -> f=5;
the variable pointed by f_p is set to t so x=3, returns f so it returns 5f = t + *f_p
which is 5+3 -> f=8;
the variable pointed by f_p is set to t so x=5, returns f so it returns 8, which is what the printf printsUpvotes: 3
Reputation: 414
Another answer revealed this to calculate the fibonacci numbers using a useful technique for returning an extra value. I've rewritten the code in what I think is a much more understandable and maintainable manner. Hope this prevents people thinking you need to write terrible code to do something like this
#include <stdio.h>
int fib(int n) {
// This is used to return the previous fib value
// i.e. fib(n - 1)
int prevValRet;
return fibRec(n, &prevValRet);
}
// *prevValRet contains fib(n-2)
int fibRec(int n, int *prevValRet) {
// Termination case
if (n <= 1) {
// return fib(0) and fib(1) as 1
*prevValRet = 1;
return 1;
}
// Calculate fib(n-1)
int prevVal = fibRec(n - 1, prevValRet);
// Calculate fib(n) = fib(n-1) + fib(n-2)
int thisVal = prevVal + *prevValRet;
// Return fib(n-1) and fib(n)
*prevValRet = prevVal;
return thisVal;
}
int main() {
printf("%d\n", fib(5));
return 0;
}
Upvotes: 1