Question

I am learning C, so I am writting some little exercises in C to practice the language.

I have experience with functional code, so I love recursion. I think that it would be great to achieve tail recursion using C static variables, so additional arguments or helper functions would not be required.

This code to calculate a factorial using recursion, fails:

long long int fact(int n)
{
    static long long int result = -1;

    if(n <= 0) {
        if(result < 0)
            return 1;
        else {
            long long int temp = result;
            result = -1;
            return temp;
        }
    } else {
        result *= n;
        fact(n - 1);
    }
}

However, for some reason, I cannot do this in C. Is there an idiom to the same that? Is it just my compiler? What about memoization?

Thanks a lot.

Was it helpful?

Solution

Your code is broken since it has a control path where it doesn't return a value. This works fine:

long long int fact(int n)
{
    static long long int result = 1;

    if(n <= 1) {
        long long int temp = result;
        result = 1;
        return temp;
    } else {
        result *= n;
        return fact(n - 1);
    }
}

GCC does successfully transform the tail recursion to iteration.

In general, I think the reason to avoid using statics for tail recursion is simply because the function loses reentrancy. So much code ends up having to run in a multithreaded environment these days that it's hard to justify leaving function-local static "landmines" in code. I do admit this is as much opinion as technical argument. The non-static tail recursive code:

static inline long long int fact_(int n, long long int result)
{
    if(n <= 1) {
        return result;
    } else {
        return fact_(n - 1, result * n);
    }
}

long long int fact(int n)
{
    return fact_(n, 1);
}

is if anything a bit easier to write - notably both versions are exactly 13 LOC - and compiles just as efficiently to iteration but without needing static data.

OTHER TIPS

You don't seem to have an explicit return value from your else block. Are you not getting compiler warnings on that? Please make sure you're compiling with all warnings turned on.

Basically, you need to add return result; to the end of your else block otherwise how are you going to return the result back to the original caller? Remember, return only pops one function call, and you're an arbitrary depth when you call return because of all the recursive calls to fact() you've made in your else block.

int factorial(int n)
{
    static int m = 1;
    m *= n;
    if (n > 1)
        factorial(n - 1);
    return m;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top