简体   繁体   English

为什么我们不能使用静态变量来实现尾递归?

[英]Why we can't use static variables to achieve tail recursion?

I am learning C, so I am writting some little exercises in C to practice the language. 我正在学习C,所以我在C中写了一些小练习来练习语言。

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. 我认为使用C静态变量来实现尾部递归会很棒,因此不需要其他参数或辅助函数。

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? 但是,由于某种原因,我无法在C语言中做到这一点。 Is it just my compiler? 只是我的编译器吗? What about memoization? 关于记忆呢?

Thanks a lot. 非常感谢。

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 . GCC确实成功将尾递归转换为迭代

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 . 如果编写起来容易一些-值得注意的是两个版本都是13 LOC, 编译效率很高,不需要静态数据

You don't seem to have an explicit return value from your else block. 您似乎在else块中没有明确的返回值。 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; 基本上,您需要添加return result; to the end of your else block otherwise how are you going to return the result back to the original caller? 到else块的末尾,否则如何将结果返回给原始调用者? 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. 记住,return只弹出一个函数调用,由于您在else块中对fact()进行的所有递归调用,所以在返回return时您处于任意深度。

int factorial(int n)
{
    static int m = 1;
    m *= n;
    if (n > 1)
        factorial(n - 1);
    return m;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM