Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 递归函数有一些限制吗?这个功能需要多少层?_C_Recursion_Stack Overflow_Collatz - Fatal编程技术网

C 递归函数有一些限制吗?这个功能需要多少层?

C 递归函数有一些限制吗?这个功能需要多少层?,c,recursion,stack-overflow,collatz,C,Recursion,Stack Overflow,Collatz,制作了一个递归函数,给出了给定起始数字的collatz序列中有多少项,这是代码n=13,例如: int collatz(long n,long o) { if (n!=1) { if(n%2==0) return collatz(n/2,o+1); else return collatz((n*3)+1,o+1); } else printf("%ld\t",o); } void ma

制作了一个递归函数,给出了给定起始数字的collatz序列中有多少项,这是代码n=13,例如:

int collatz(long n,long o)
{
    if (n!=1) {
        if(n%2==0)
            return collatz(n/2,o+1);
        else
            return collatz((n*3)+1,o+1);
    } else
        printf("%ld\t",o);
}
void main()
{
    collatz(13,0);
}
函数按预期运行;但是,对于一些整数,例如“n=113383”,有些东西溢出(我猜)并返回:

Process returned -1073741571 (0xC00000FD)   execution time : 4.631 s
Press any key to continue.

请原谅我的非技术性解释,非常感谢

这里发生的是堆栈溢出。这是因为函数的每次调用都会创建一个新的堆栈帧,如果堆栈帧太多,堆栈的内存就会耗尽。您可以通过使用迭代而不是递归来修复它

另外,
long
可能无法保存collatz序列为
113383
的起始值生成的数字(我在MSVC中没有)。改为使用
long
,至少64位大。总而言之,它可能是这样的:

void collatz(long long n)
{
    long o;
    for (o = 0; n > 1; o++) {
        if (n % 2 == 0)
            n /= 2;
        else
            n = n * 3 + 1;
    }
    printf("%ld\t", o);
    return;
}

int main()
{
    collatz(113383);
    return 0;
}

请注意,我们现在有一个
for
循环,而不是递归。

在C标准本身中,递归深度没有限制。您可能会导致堆栈溢出,但堆栈大小在不同的环境中是不同的。我认为Windows有1MB,Linux有8MB。它还取决于函数堆栈帧的大小,而堆栈帧的大小又取决于它有多少变量和类型

在本例中,您有两个
long
变量,每个变量可能有8个字节。您还有字符串
“%ld\t”
,它是5个字节,可能会在堆栈上结束,但我不确定。除此之外,还有两个指向函数返回地址和上一个堆栈帧的指针的开销,在64位系统上,每个指针都是8字节。因此,函数的堆栈帧大约是32字节左右。也许再多一点。所以在Linux系统上,我猜你的函数会在大约20万的深度崩溃

如果这是一个问题,考虑将函数重写为非递归变量。看看Blaze的答案,了解如何为您的案例做到这一点。正如安德烈在下面评论的那样:


附加说明:您可以在Linux下使用ulimit-s(也可以使用ulimit-s unlimited)增加堆栈大小,在MSVC中,您可以设置/F编译标志以增加程序的堆栈大小。有关MinGW,请参阅post


函数不会为
n==1
返回任何值。当函数到达
printf
时,函数不会
返回值。也许你应该
返回o
而不是打印collatz中的值,并在调用函数中打印结果。0xC00000FD表示堆栈溢出。是的,堆栈大小有限。为了更好地理解functionality@500-InternalServerError谢谢,虽然我的系统相对强大,但是堆栈是静态的吗?这意味着系统之间的音量是否会发生变化?附加说明:在Linux下,您可以使用(也可以是:
ulimit-s unlimited
)增加堆栈大小,在MSVC中,您可以设置/compilation标志以增加程序的堆栈大小。关于MinGW,请参阅帖子。回答不错。我对格式做了一些改进。希望你不介意。@Broman一点也不介意!谢谢你的修复。我也很感谢你的回答,它为OP提供了更多的技术见解。