C 为什么输出之间存在差异? #包括 无效计数(int); 无效计数(整数n) { int d=1; printf(“%d”,n); printf(“%d”,d); d++; 如果(n>1)计数(n-1); printf(“%d”,d); } 内部主(空){ 计数(3); 返回0; }

C 为什么输出之间存在差异? #包括 无效计数(int); 无效计数(整数n) { int d=1; printf(“%d”,n); printf(“%d”,d); d++; 如果(n>1)计数(n-1); printf(“%d”,d); } 内部主(空){ 计数(3); 返回0; },c,recursion,static,C,Recursion,Static,输出:312 #包括 无效计数(int); 无效计数(整数n) { 静态int d=1; printf(“%d”,n); printf(“%d”,d); d++; 如果(n>1)计数(n-1); printf(“%d”,d); } 内部主(空){ 计数(3); 返回0; } 输出:3 1 2 3 4 4 在这两个输出中,我无法获得输出中最后3位数字之间的差异,即444和222 我知道静态声明在编译时有静态分配,所以它的值在整个程序中都会保留,并且在函数调用结束时本地/自动变量就会被销毁

输出:312


#包括
无效计数(int);
无效计数(整数n)
{
静态int d=1;
printf(“%d”,n);
printf(“%d”,d);
d++;
如果(n>1)计数(n-1);
printf(“%d”,d);
} 
内部主(空){
计数(3);
返回0;
}
输出:3 1 2 3 4 4


在这两个输出中,我无法获得输出中最后3位数字之间的差异,即444222

我知道静态声明在编译时有静态分配,所以它的值在整个程序中都会保留,并且在函数调用结束时本地/自动变量就会被销毁


但是,尽管我对最后三位数字感到困惑,因为我无法根据上述信息解释它们?

最后三位数字是
d
的值,在对
count
的任何和所有递归调用完成后可见

在第一个程序中,
d
的作用域是对
count
的每个单独调用,并且它在每个堆栈帧中只增加
1
1+1=2
,函数在退出前打印
2

在第二个程序中,
d
对程序是静态的,并且在每次调用
count
时共享。如前所述,最终的print语句仅在对
count
的所有调用都已运行之后才会出现,并且不再对
count
进行调用,因此
d
在这里将始终处于其最大值-无论对
count
的哪个调用结束。

在此函数中

#include <stdio.h>
void count(int );

void count(int n)
{
    static int d = 1;
    printf("%d ", n);
    printf("%d ", d);
    d++;
    if(n > 1) count(n-1);
    printf("%d ", d);
} 

int main(void) {
    count(3);
    return 0;
}
局部变量
d
具有静态存储持续时间,它在函数调用之间保持其值。在程序启动之前,它只初始化一次

所以在这个代码片段中

void count(int n)
{
    static int d = 1;
    ^^^^^^^^^^^^^^^^^
    printf("%d ", n);
    printf("%d ", d);
    d++;
    if(n > 1) count(n-1);
    printf("%d ", d);
} 
当在最内部的调用中变量
d
已经获得其值4时,执行最后一条语句

你可以这样想象

    if(n > 1) count(n-1);
    printf("%d ", d);
函数末尾的
printf()
将首先针对
计数(n=1)
案例运行。返回后,
printf()
运行
count(n=2)
,然后运行
count(n=3)


在非静态情况下,局部变量
d
在函数末尾始终为2。在静态情况下,所有变量都共享同一个变量,因此在最后一次
count()
增加它之后,它将是4

尝试以下方法,以便更好地了解发生了什么:

d++;
d++;
d++;
//...

printf("%d ", d);
printf("%d ", d);
printf("%d ", d);

进行递归调用时,直到递归结束,才会执行调用后的语句。这包括所有嵌套的递归调用。以下是使用自动变量调用版本时发生的情况:

  • main()
    调用
    count(3)
    • 初始化
      d=1
    • 打印
      n
      ,其中包含
      3
    • 打印
      d
      ,其中包含
      1
    • 递增
      d
      ,现在它包含
      2
    • 呼叫计数(n-1)
      • 初始化
        d=1
      • 打印
        n
        ,其中包含
        2
      • 打印
        d
        ,其中包含
        1
      • 递增
        d
        ,现在它包含
        2
      • 呼叫计数(n-1)
        • 初始化
          d=1
        • 打印
          n
          ,其中包含
          1
        • 打印
          d
          ,其中包含
          1
        • 递增
          d
          ,现在它包含
          2
        • 如果(n>1)
          失败,那么它不会递归
        • 打印
          d
          ,其中包含
          2
        • 返回
      • 打印
        d
        ,其中包含
        2
      • 返回
    • 打印
      d
      ,其中包含
      2
    • 返回
如果您找到上面所有的
print
行,它将打印
3 1 2 2

下面是使用带有静态变量的版本时发生的情况:

  • main()
    调用
    count(3)
    • 初始化
      d=1
      ,因为这是对函数的第一次调用
    • 打印
      n
      ,其中包含
      3
    • 打印
      d
      ,其中包含
      1
    • 递增
      d
      ,现在它包含
      2
    • 呼叫计数(n-1)
      • 打印
        n
        ,其中包含
        2
      • 打印
        d
        ,其中包含
        2
      • 增加
        d
        ,现在它包含
        3
      • 呼叫计数(n-1)
        • 打印
          n
          ,其中包含
          1
        • 打印
          d
          ,其中包含
          3
        • 递增
          d
          ,现在它包含
          4
        • 如果(n>1)
          失败,那么它不会递归
        • 打印
          d
          ,其中包含
          4
        • 返回
      • 打印
        d
        ,其中包含
        4
      • 返回
    • 打印
      d
      ,其中包含
      4
    • 返回
提取所有
print
行,它将打印
3 1 2 3 4 4


不同之处在于,
d
在每次调用函数时都会不断变高,因为它保留了上一次调用的值,然后递增。

在第一个程序中,
d
自动
变量,因此,每次执行功能时,
d
的内存被保留,功能完成后,它将不被保留

d++;
d++;
d++;
//...

printf("%d ", d);
printf("%d ", d);
printf("%d ", d);
void count(int n)
{
    static int d = 1;
    d++;
    printf("%d: pre recursion (d = %d)\n", n, d);
    if(n > 1) count(n-1);
    printf("%d: post recursion (d = %d)\n", n, d);
}