1

下面是一个示例 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没有调用next。输出似乎不自然。我搜索了互联网,发现了一些关于堆栈的东西。有人可以详细说明为什么会这样吗?

4

3 回答 3

3

这是一个基本的递归调用。

首先,请注意,对于n小于 50 的值,您的函数将打印n两次,而对于其他值,n它将仅打印一次。这与你的输出一致,所以这里唯一要弄清楚的是顺序......

第二个注意, for 的输出n*2应该位于n(for )的第一行和第二行输出之间,因为您在两个s之间n < 50进行递归调用。好吧,这与您的输出一致。printf

这正如预期的那样。

您在互联网上找到的有关堆栈的部分是指调用堆栈。为了从函数返回,程序必须跟踪调用函数时的位置。此信息被写入称为“调用堆栈”或“执行堆栈”的内存特殊部分的“末尾”;并且它从堆栈中取出(意味着当函数返回时移动'end')。调用参数也记录在堆栈上。

这种堆叠对于递归是必不可少的。

因此,当您调用newfunc(2)程序时记录它在第 5 行,然后跳转到第newfunc8 行的开头。堆栈看起来(理论上)如下所示:

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 

堆栈内容的确切格式取决于芯片的体系结构和操作系统程序员做出的一些决定。


顺便说一句--ac 程序通常不使用行号来表示“位置”,这是因为行在 c 中不是很好的度量(如果我够傻的话,我可以将整个程序写成一行),而是使用值芯片上的寄存器,但这并不真正影响这里的解释。

于 2012-10-29T17:08:39.303 回答
0

实际发生的是,当您在第 13 行调用该函数时,该函数之后的代码当时无法执行,因此它们存储在内存中称为堆栈的特殊位置,它们从底部填充,因此较新的代码填充顶部的堆栈。因此,在第一次函数调用时,printf("\n%d",2)将添加到堆栈的底部printf("\n%d",4);2 * n = 2 * 2 = 4 被添加到一个堆栈的顶部,并且当递归执行停止时。从顶部开始执行堆栈程序,产生上述复杂类型的输出,简单分析无法预测。

于 2012-10-29T17:01:52.293 回答
0

让我们把它当作小值说 10

1st call from main         ////returned from newfunc(2)
newfunc(2)             
//inside newfunc(2)
print 2
2<10 (correct)
newfunc(4)  --> on stack print 2  //returned from newfunc(4)
-------------------------------
//inside newfunc(4)
print 4 
4<10
newfunc(8)  --> on stack print 4 //returned from newfunc(8)
---------------------------------
//inside newfunc(8)
print 8
8<10
newfunc(16) --> on stack print 8 //returned from newfunc(16)
---------------------------
//inside newfunc(16)
print 16
16<10 failed

所以它会return调用它之​​前的函数,所以它将继续在-->此示例中位于堆栈顶部的符号,print用于result在屏幕上显示

功能顺序是自上而下的......我试图在图表中显示这一点。希望你明白。

here-->语句将从下到上执行,因此结果将是

2
4
8
16
8
4
2
于 2012-10-29T17:13:48.110 回答