#include <stdio.h>
void reverseSentence();
int main() {
printf("Enter a sentence: ");
reverseSentence();
return 0;
}
void reverseSentence() { //(1)
char c;
scanf("%c", &c); //input: abc (2)
if (c != '\n') { (3)
printf("%c-",c); //output1: a-b-c- (4)
reverseSentence(); // call reserseSentence (5)
printf("%c", c); // output2 will return after output1 finish : cba (6)
}
}
显示:a-b-c-cba
该程序将在void
reverseSentence()
中运行:
1-> 2-> 3-> 4-> 5-> 1-> 2-> 3-> 4-> 5-> 1-> 2-> 3-> 4-> 5-> 6- > 5-> 6-> 5-> 6
您能解释一下它是如何工作的吗?
为什么c
变量可以存储所有值?
答案 0 :(得分:2)
这里的问题似乎是对局部变量如何工作的理解。我将使用简化的模型,其中仅将堆栈用于局部变量。
当main
调用reverseSentence
时,局部变量(c
)被分配在堆栈上:
+--------+
| c | <------current running copy of reverseSentence
+--------+
| main |
在声明之后,reverseSentence
再次调用reverseSentence
。因此,将在堆栈上创建下一个副本:
+--------+
| c | <------current running reverseSentence
+--------+
| c | <------previous running reverseSentence
+--------+
| main |
随着越来越多的递归调用,堆栈会获得更多的c
变量。
返回reverseSentence
时,该运行版本的本地变量将被销毁。
+--------+
| xxxxxx | <----- reverseSentence that returned
+--------+
| c | <------current running copy of reverseSentence
+--------+
| main |
实际上,该模型要复杂一些。根据处理器的体系结构,堆栈可能包含返回地址或指向上下文等的指针。但是,作为第一个关于局部变量如何工作的模型,这应该足够了。
答案 1 :(得分:1)
我认为图片会更清晰,f代表reverseSentence。
答案 2 :(得分:0)
scanf()
一次将只吃一个字符,因此每次重复执行reverseSentence()
时,它都会转到下一个字符,直到命中换行符,然后if测试不通过并且递归结束。由于通过递归的工作方式,最后一个实例执行了最后一个printf
,因此您在出局时得到了cba
。
从某种意义上讲,您可以考虑输入“ abc”作为错误:原因是如上所述,程序一次只能将一个字符放入c
中。通常,这不是处理用户输入的好方法:最好将其设置为一个数组,以在其中处理整个输入字符串。在其中引入递归只会无缘无故地变得混乱。
答案 3 :(得分:0)
char c
不存储数据,每次它将用scanf
读取一个字符并打印,然后,由于这是一个递归函数,它将首先移至输入的最后一个字符,从头到尾打印它们。
该程序不会反转句子,因为没有句子,它只是读取一些字符并使用递归功能将它们从最后一个打印到第一个。
但是此代码花费的时间太长,不建议使用,相反,您可以定义一个字符串并将其作为输入,然后从最后到第一打印(\0
除外),但是即使该方法也不会反转句子,您的程序和此方法都将从最后开始打印。
答案 4 :(得分:0)
函数的变量不使用固定的存储位置。每次调用函数时,它都会获取新的内存位置以用于其变量。
大多数系统实现此目的的方式是整个程序都有一个称为 stack 的保留内存区域。有一个堆栈指针(SP),用于指示正在使用的堆栈的当前部分。每当函数启动时,它都会将SP更改为指向堆栈中的新区域。然后,将其所有局部变量存储在相对于新SP值的位置,例如SP + 4,SP + 8,SP + 24等。该函数返回时,它将SP恢复为先前的值。
因此,每次对c
的呼叫中的reverseSentence
位于不同的位置。
通常,堆栈指针从操作系统和程序加载器确定的某个高地址开始,并且向“下方”增长,这意味着,当函数在堆栈上需要更多空间时,它将从中减去一些数字。堆栈指针以给出一个较低的地址。当函数返回时,它通过添加相同的数字(或通过从保存它的位置加载以前的堆栈指针值)来反转该值。