如何创建跟踪以显示存在递归的调用顺序

How can I create a trace which shows the call order where there is recursion

本文关键字:存在 显示 递归 顺序 调用 跟踪 何创建 创建      更新时间:2023-10-16

我想知道有关执行递归函数的详细信息。

#include<iostream>
int a=0;
int fac(int n) {
if (n <= 1)
return n;
int temp = fac(n-2) + fac(n - 1);
a++;
return temp;
}
int main() {
fac(4);
std::cout<<a;
}

输出为 4。

我想知道int temp = fac(n-2) + fac(n - 1);是什么时候执行的,例如 fac(4-2)+fac(4-1) ---> fac(2)+fac(3),这时编译器会先完成 fac(2)? 还是一起完成? 我英语不好,希望你的阅读没有障碍。

纯粹从算法意义上分析此代码,而不考虑C++实现的复杂性,

fac(4)
fac(2)         +            fac(3)
|----------------------------|
fac(0) + fac(1)              fac(1) + fac(2)
1    +   1                    1   + fac(0) + fac(1)
+   1    +   1

如何创建跟踪以显示存在递归的调用顺序?

首先,我要注意的是,编译器生成的编译器输出不会与您编写的代码一对一匹配。编译器根据提供给它的标志应用不同级别的优化,最高级别是-O3,默认值是-O0,但这些似乎超出了这个问题的范围。创建跟踪会影响此过程本身,因为编译器现在需要满足您对跟踪外观的期望。跟踪实际执行流的唯一真正方法是读取编译器生成的程序集。

知道了这一点,我们可以应用跟踪来查看调用顺序,方法是在执行进入被调用方法时打印到屏幕上。请注意,我已经删除了a因为它并没有真正跟踪任何内容,只会增加解释的复杂性。

int fac(int n) {
std::cout << "fac(" << n << ")" << std::endl;
if (n <= 1)
return n;
int temp = fac(n-2) + fac(n - 1);
return temp;
}
int main() {
fac(4);
}
// Output
fac(4)
fac(2)
fac(0)
fac(1)
fac(3)
fac(1)
fac(2)
fac(0)
fac(1)

如我电脑上的此输出所示,执行首先从左到右深度进行。我们可以用这个顺序对调用树进行编号,以获得更好的图片,

// Call order
1. fac(4)
2. fac(2)         +         5. fac(3)
|----------------------------|
3. fac(0) + 4. fac(1)        6. fac(1) + 7. fac(2)
+ 8. fac(0) + 9. fac(1)

注意:这并不意味着每个实现的结果都相同,也不意味着当您删除跟踪并允许编译器优化时,执行顺序会保留,但它演示了递归在计算机编程中的工作原理。

首先fac(2)将完成,然后是fac(1)。输出为 4。

调用堆栈将是这样的(从下到) -

|---fac(1)
|--- fac(2) |
|---- fac(3) |           |---fac(0)
|            |
|            |----fac(1)
|
fac(4) |
|
|            |---- fac(1)
|---- fac(2) |
|---- fac(0)

n <= 1时将返回fac()函数