静态函数中是否可以使用递归?

7

在C语言中是否可以编写递归的静态函数?


1
为什么不应该呢?static 意味着函数是局部于文件的。 - Anton
2
你为什么认为这不可能呢?不如试一试? - helpermethod
2
为什么要关闭投票?对我来说,这似乎很简单,我肯定不是这里最聪明的人 :-) 投票重新开放。 - paxdiablo
4
我投票支持重新开放。花了一点时间,但他想要表达的意思很明确。 - Tim Post
2个回答

17

没错,这绝对没问题。当你在函数上应用static时,它与递归函数中的静态变量不同(如果在计算中使用,则会有问题)。

当应用于函数(或函数外的对象)时,static仅控制该内容是否可在编译单元外部可见(例如对于链接器)。

当应用于函数内的对象时,static意味着该变量存在于函数的持续时间之外。在递归函数的上下文中,它还意味着只有一个变量副本供所有递归级别使用,而不是每个递归级别都需要一个新变量,通常情况下这是必要的。

所以,这(您问题似乎在询问此内容)是完全没有问题的:

static unsigned int fact (unsigned int n) {
    if (n == 1U) return 1;
    return n * fact (n-1);
}

相反的,这样做是不好的,因为静态变量的唯一副本很可能会被较低递归层次的操作破坏。

static unsigned int fact (unsigned int n) {
    static unsigned int local_n;
    local_n = n;
    if (local_n == 1U) return 1;
    return fact (local_n - 1) * local_n;
}

更详细地说,考虑对 fact(3) 的调用:

  • 在第一层递归中,将 local_n 设置为 3,然后调用 fact(2)
  • 在第二层,将 local_n 设置为 2,并调用 fact(1)
  • 在第三层,将 local_n 设置为 1,由于这是递归的基本情况,所以直接返回 1

事情似乎从那时候开始出了问题(尽管严格来说,它们从我们为声明符 local_n 输入 static 关键字时就开始出了问题):

  • 回到第二层,我们收到 1 并将其乘以 local_n。如果该变量不是静态的,则会具有值 2(即上一步中的局部值)。不幸的是,它静态的,因此在上一步中设置为 1。因此我们返回 1 * 1 或者…等等,让我在计算器上检查一下…,1 :-)
  • 回到第一层同理,我们得到 1 并将其乘以 local_n,但是当然,local_n 仍然具有值 1。因此我们再次相乘并返回 1

如果您想尝试,这里是一个完整的程序:

#include <stdio.h>

static unsigned int fact (unsigned int n) {
    static unsigned int local_n; // bad idea!
    local_n = n;
    if (local_n == 1U) return 1;
    return fact (local_n - 1) * local_n;
}

int main() {
    printf("%d\n", fact(3));
    return 0;
}

如果你去掉local_n声明中的static关键字,它将返回正确的6,而不是错误的1


4
#include <stdio.h>

static void count_to_five(void)
{
   static int i = 0;

   while (i < 5) {
     i++;
     printf("%d\n", i);
     count_to_five();
   }

  puts("You are seeing this because I counted to five! (did not enter loop)\n");    
  return;
}

int main(void)
{
    count_to_five();
    return 0;
}

所以,是的。注意,i 的静态存储意味着它在每次调用 count_to_five() 时都会保留其值。然而,count_to_five() 不需要被定义为 static
很难理解你在问什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接