Pointers on C——7 Functions.6

来源:互联网 发布:部落冲突女皇升级数据 编辑:程序博客网 时间:2024/06/15 06:37

7.5.1 Tracing a Recursive Function

But in order to understand how recursion works in the first place, you need to trace the execution of the recursive calls. So letʹs do that now. The key to following the execution of a recursive function is understanding how the variables declared inn a function are stored. When a function is called, space for its variables is created on the runtime stack. The variables belonging to the previous functions remain on the stack,but they are covered up by the new ones and are inaccessible.

但是,为了能理解递归的工作原理,你要追踪递归调用的执行过程,所以让我们来进行这项追踪个递归函数执行过程的关键是理解函数中所声明的变量是如何存储的当函数被调用时,它的变量的空间是创建于运行时堆栈上的以前调用的函数的变仍保留在堆栈上,但它们被新函数的变量所掩盖,因此是不能被访问的


When a recursive function calls itself, the same thing happens. A new set of variables is created for the new call, which cover up the variables that belong to the previous call(s) to this function. When tracing the execution of a recursive function, we must keep these different sets of variables separate from one another to avoid confusion.

当递归函数调用自身时,情况也是如此每进行一次新的调用,都将创建批变量,它们将掩盖递归函数前次调用所创建的变量。当我们追踪个递归函数的执行过程时,必须把分属不同次调用的变区分开来,以避免混淆


The function in Program 7.6 has two variables: the argument value and the local variable quotient. The following diagrams show the state of the stack, with the set of variables currently being accessed on the top of the stack. All other sets of variables are shaded in gray, because (hey are inaccessible to the function currently executing.

程序7.6 的函数有两个变量:参数value 和局部变量quotient下面的一些图显示了堆栈的状态,前可以访问的变量位于栈顶所有其他调用的变饰以灰色阴影,表示它们不能被当前正在执行的函数访问


Suppose we call the function with the value 4267. Here is what the stack looks like as the function begins to execute.

假定我们以4267 这个值调用递归函数。当函数刚开始执行时,堆栈的内容如下图所示



After the division occurs, the stack looks like this.

执行除法运算之后,堆栈的内容如下:


Next, the if statement determines that the quotient is not zero and makes a recursive call to the function. Here is what the stack looks like as the second call of the function begins.

接着, if 语句判断出quotient 的值非零,所以对该函数执行递归调用。当这个函数次被用之初,堆栈的内容如下:



A new set of variables has been created on the stack, hiding the previous set, which will remain inaccessible until this recursive call to the function returns. After the division, the stack looks like this.

创建了批新的变,隐藏了前面的那批变量,除非前这次递归调用返回,否则它们是不能被访问的再次执行除法运算之后,堆的内容如下:


The quotient has the value 42, which is nonzero, so we get another recursive call with another set of variables. After the division, the stack looks like this:

quotient 的值现在为42 , 仍然非零,所以需要继续执行递归调用, 再创批变量。在执行完这次调用的除法运算之后,堆栈的容如下:


The quotient is still nonzero, so another recursive call is made. After the division, the stack looks like this:

此时, quotient 的值还是非零,仍然要执行递归调用在执行除法运算之后,堆栈的内容如下:


Disregarding the recursive call itself, the only statements that have been executed so far are the division and the test of the quotient. Because the recursive call has caused these statements to be repeated, the effect is similar to that of a loop; while the quotient is nonzero, use it as the initial value and start over again. But the recursion saves information that a loop would not, the stacked values of the variables. This information is about to become important.

不算递归调用语句本身,到目前为止所执行的语句只是除法运算以及对quotient 的值进行测试。由于递归调用使这些语句重复执行,所以它的效果类似循环quotient 的值非零时,把它的值作为初始值重新开始循环。但是,递归调用将会保存些信息〈这点与循环不同),也就是保存在堆栈中的变量值这些信息很快就会变得非常重要


The quotient is zero, so the function does not call itself again. Instead, it begins to print output. The function then returns, which begins to remove values from the stack.

现在quotient 的值变成了零,递归函数便不再调用自身,而是开始打印输出然后函数返回,并开始销毁堆栈上的变量值。


Each call to putchar gets the last digit of the value by taking the value moduloten. The result is an integer in the range zero to nine; the character constant for a zero is added in order to get the ASCII character that corresponds to the digit, which is printed.

每次调用putchar 得到变value 的最后一个数字,方法是对value 进行模10的 取余运算, 其结果个0 到9 之间的整数把它与字符常'0' 相加,其结果便是对应于这个数字的ASCII 字符,然后把这个符打印出来


The function then returns, and its variables are discarded from the stack. The previous invocation of the function then continues to execute from the point of the recursive call using its own variables, which are now on the top of the stack. Because its value is 42, the call to putchar prints the digit two.

接着函数返回,它的变量从堆栈中销毁。接着,递归函数的前次调用重新继续执行,它所使用的是自己的变量,它们现在位于堆栈的顶部。因为它的value 值是42 ,所以调用putchar 后打印出来的数字是2 


This invocation of the function then returns, which uncovers the variables for the previous invocation. Execution continues there from the point of the recursive call, and a six is printed. Just before the function returns again, the stack looks like this:

接着递归函数的这次调用也返回,它的变也被销毁,此时位于堆栈顶部的是递归函数再前次调用的变量。递归调用从这个位置继续执行,这次打印的数是6 在这次调用返回之前,堆栈的内容如下:


We have now unwound the recursion and are back to the original call to the function.It prints the digit seven, which is the remainder of its value divided by ten.

现在我们已经展开了整个递归过程,并回到该函数最初的调用这次调用打印出数字7 ,也就是它的value 参数除10 的余数


The function then returns to whatever other function called it.

然后,这个递归函数就彻底返回到其他函数调用它的地点


If you put all of the characters that were printed side by side as they would appear on a printer or screen, you will see the correct value: 4267.

如果你把打印出来的个接个排在起,出现在打印机或屏幕上,你将看到正确的值:4267 

上一章 Pointers on C——7 Functions.5