如何手动分析递归源代码?

如何手动分析递归源代码?

例如,我设计了一种手工分析迭代源代码的技术,如下所示:

int fact(int n) { int f = 0; int i = 0; if (n<=1) { return 1; } f = 1; i = 2; for (i=2; i<=n ; i++) { f *= i; } return f; } --------------------------- if new-f --------------------------- --------------------------- --------------------------- 

对于每个’i’,我可以手动分析和计算old-f和new-f的值,并填写表格以查看例程是否正常工作。

但是如何手动分析递归例程?

 int fact(int number) { int temp; if(number <= 1) return 1; temp = number * fact(number - 1); return temp; } 

由于递归将值存储在堆栈上,因此需要对其进行双向分析

第一遍是:进行递归直到达到终止条件。

第二遍:收集值,直到堆栈为空。

 1st down 2nd up --------------------------------- n = 6 tmp = 6 * 120 = 720 <- result n = 5 tmp = 5 * 24 = 120 n = 4 tmp = 4 * 6 = 24 n = 3 tmp = 3 * 2 = 6 n = 2 tmp = 2 * 1 = 2 n = 1 end 

您可以使用调试器来执行此操作,而无需更改原始代码或编写新代码。 1.在名为fact 2的函数的地址处设置断点。运行调试器,每次在断点处停止时,都可以检出参数号的值和返回值

在处理递归函数时,有效表达函数正在执行的操作的方法是将其视为数学函数并简化函数的应用。 虽然这不会真正告诉你函数的内部状态(在这种情况下,是temp的值),但它为你提供了一种描述函数的非常好的方法。

对于阶乘的例子,我们可以将事实定义为:

 fact(x) = 1 when x <= 1 fact(x) = x * fact(x - 1) otherwise 

现在,当你想表达它是如何工作的时候,你选择一个小的起始编号(比如6)和......

 fact(6) = 6 * fact(5) = 6 * 5 * fact(4) = 6 * 5 * 4 * fact(3) 

等等。

这样,您正在做的是分析函数的结构而不是它的实现。 现在出于调试目的,这不太有用(至少不是非function性语言)。 但它对评论,文档和沟通非常有用。