在C语言中是否可以编写递归的静态函数?
没错,这绝对没问题。当你在函数上应用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
。
#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
。