为什么输出之间存在差异?

时间:2017-02-04 15:19:56

标签: c recursion static

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

void count(int n)
{
    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;
}

输出: 3 1 2 1 1 1 2 2 2

#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;
}

输出: 3 1 2 2 1 3 4 4 4

在两个输出中,我无法得出输出中最后3位数之间的差异,即 444 222

我知道静态声明在编译时有静态分配,所以它的值在整个程序中保留,并且一旦函数调用结束就会销毁local / auto变量。

但是,即使我在最后3位数字中感到困惑,因为我无法根据上述信息解释它们?

5 个答案:

答案 0 :(得分:3)

您的函数末尾的printf()将首先针对count(n=1)案例运行。返回后,printf()将针对count(n=2)运行,然后针对count(n=3)运行。

在非静态情况下,局部变量d在函数末尾始终为2。在静态情况下,all共享相同的变量,因此在最后count()递增后它将为4。

尝试这样的事情,以便更好地了解会发生什么:

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);
} 

答案 1 :(得分:3)

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

  • main()来电count(3)
    • 初始化d = 1
    • 打印n,其中包含3
    • 打印d,其中包含1
    • 增加d,现在包含2
    • 致电count(n-1)
      • 初始化d = 1
      • 打印n,其中包含2
      • 打印d,其中包含1
      • 增加d,现在包含2
      • 致电count(n-1)
        • 初始化d = 1
        • 打印n,其中包含1
        • 打印d,其中包含1
        • 增加d,现在包含2
        • if (n > 1)失败,所以它没有递归
        • 打印d,其中包含2
        • 返回
      • 打印d,其中包含2
      • 返回
    • 打印d,其中包含2
    • 返回

如果您找到上面的所有print行,则会打印3 1 2 1 1 1 2 2 2

以下是使用带有静态变量的版本时会发生什么:

  • main()来电count(3)
    • 初始化d = 1,因为这是对函数的第一次调用
    • 打印n,其中包含3
    • 打印d,其中包含1
    • 增加d,现在包含2
    • 致电count(n-1)
      • 打印n,其中包含2
      • 打印d,其中包含2
      • 增加d,现在包含3
      • 致电count(n-1)
        • 打印n,其中包含1
        • 打印d,其中包含3
        • 增加d,现在包含4
        • if (n > 1)失败,所以它没有递归
        • 打印d,其中包含4
        • 返回
      • 打印d,其中包含4
      • 返回
    • 打印d,其中包含4
    • 返回

提取所有print行,然后打印3 1 2 2 1 3 4 4 4

不同之处在于每次调用函数时d都会持续变高,因为它会保留前一次调用的值,然后会增加。

答案 2 :(得分:2)

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

在第一个程序中,d的范围限定为对count的每个单独调用,并且它在每个堆栈帧中仅增加11 + 1 = 2,函数在退出前打印2

在第二个程序中,d静态到程序中,并在每次调用count之间共享。如前所述,最终的打印语句仅在所有count调用开始后才会发生,并且将不再有count的调用,因此d将始终处于其最大值 - 无论对count的哪个电话正在结束。

答案 3 :(得分:0)

在此功能中

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具有静态存储持续时间,它在函数调用之间保持其值。它在程序启动前只初始化一次。

所以在这段代码中

    if(n > 1) count(n-1);
    printf("%d ", d);

在最内层调用中执行最后一个语句,变量d已经获得其值4.

你可以通过以下方式想象它

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

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

答案 4 :(得分:0)

在第一个程序d中是auto变量,因此,每次执行函数时都会保留d的内存,并且在完成函数后它是未保留的。

在第二个程序中,dstatic变量,因此,第一次保留函数d变量内存的执行但是在编译函数之后它不是未保留的。仅当整个程序完成时,static变量内存才会被保留。