下面是一个示例C程序,它提供程序之后的输出

#include<stdio.h>
void newfunc(int n);
int main(void)
{
    newfunc(2);
    return 0;
}
void newfunc(int n)
{
    printf("\n%d",n);
    if(n<50)
    {
        newfunc(2*n);
        printf("\n%d",n);
    }
}

产生输出
2
4
8
16
32
64
32
16
8
4
2

但根据代码,在第13行中的函数调用之后,似乎没有调用下一个printf。结果似乎不自然。我在网上搜索了一下,发现了一些关于堆栈的东西。有人能解释一下为什么会这样吗?

最佳答案

这是一个基本的递归调用。
首先,注意对于n小于50的值,函数将打印n两次,而对于n的其他值,函数将只打印一次。这与你的输出一致,所以这里唯一要弄清楚的是顺序。。。
第二,注意n*2的输出应该在n的第一行和第二行之间(对于n < 50),因为您在这两个printf之间进行递归调用,这也与您的输出一致。
这是意料之中的。
你在网上找到的关于堆栈的部分是指调用堆栈。为了从函数返回,程序必须跟踪调用函数时的位置。该信息被写入内存中称为“调用堆栈”或“执行堆栈”的特殊部分的“end”;并从堆栈中取出(意味着当函数返回时“end”被移动)。调用参数也记录在堆栈上。
这种叠加是递归的必要条件。
所以,当您调用newfunc(2)时,程序记录它在第5行,然后跳到第8行newfunc的开头。堆栈看起来(概念上)像:

line 5, n=2

当它到达第13行时,它再次调用新函数,使堆栈
line 5, n=2; line 13, n=4

这个过程持续了好几次直到堆栈看起来像
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32; line 13, n=64

当if失败并且newfunc返回弹出堆栈并在第13行(因为这是我们从堆栈中得到的)生成堆栈之后继续执行时
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16; line 13, n=32

当我们运行printf并在返回第13行时弹出堆栈(弹出时得到的结果,右>)时,堆栈是
line 5, n=2; line 13, n=4; line 13, n=8; line 13, n=16;

等等,当它展开整个调用堆栈时。
最后几个细节:堆栈在概念上是“向上”增长的,因此我们通常将其写成
line 13, n=32
line 13, n=16
line 13, n=8
line 13, n=4
line 5, n=2

堆栈内容的确切格式取决于芯片的结构和操作系统程序员的一些决定。
顺便说一句,c程序通常不使用行号来表示“在哪里”,因为在c语言中,行不是很好的度量单位(如果我够傻的话,我可以把整个程序写一行),而是使用芯片上寄存器的值,但这并不真正影响这里的解释。

10-05 22:05