#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)
    }
}

显示:abc-cba

void reverseSentence()程序中将工作:

1 -> 2 -> 3 -> 4 -> 5 -> 1 -> 2 -> 3 -> 4 -> 5 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 5 - > 6 ->5 -> 6

你能解释一下它是如何工作的吗?为什么c变量可以存储所有值?


这里的问题似乎是对局部变量如何工作的理解。我将使用一个简化模型,其中堆栈仅用于局部变量。

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   |

实际上,该模型有点复杂。根据处理器的体系结构,堆栈可能包含返回地址或指向上下文的指针等。但作为局部变量如何工作的第一个模型,这应该足够了。


我觉得图片会更清晰,f代表reverseSentence。

enter image description here enter image description here enter image description here


scanf()将一次吃一个字符,因此每次reverseSentence()重复它都会转到下一个直到它碰到换行符然后 if 测试不进行并且递归结束。由于递归的工作原理是 last instance 执行 last printf,因此您可以cba退出。

从某种意义上说,您可以将输入“abc”视为错误:原因是如前所述,该程序一次只会将一个字符放入c. 这通常不是处理用户输入的好方法:最好将其设为处理整个输入字符串的数组。将递归引入其中只会无缘无故地使它变得混乱。


char c不存储数据,每次它会读取一个字符并scanf打印它然后,因为这是一个递归函数,它会首先转到输入的最后一个字符并从头到尾打印它们。

这个程序没有反转句子,因为没有句子,它只是读取一些字符并使用递归函数从最后一个打印到第一个。

但是这段代码太长了,不建议,而是你可以定义一个字符串并将其作为输入,然后从最后到第打印它(除了\0),但即使这种方法也没有反转句子,你的程序和这个方法都是从最后到第一打印。


函数不为其变量使用固定的内存位置。每次调用函数时,它都会获得新的内存位置以用于其变量。

大多数系统实现这一点的方式是整个程序都有一个称为堆栈的保留内存区域有一个堆栈指针 (SP) 指示正在使用的堆栈的当前部分。每当函数启动时,它都会更改 SP 以指向堆栈中的新区域。然后它将所有局部变量存储在与新 SP 值相关的位置,例如 SP+4、SP+8、SP+24 等。当函数返回时,它会将 SP 恢复为其先前的值。

因此,c在每次调用中reverseSentence都位于不同的位置。

最常见的是,堆栈指针从操作系统和程序加载器确定的某个高地址开始,并且“向下”增长,这意味着,当函数需要堆栈上的更多空间时,它会从堆栈指针中减去一些数字给一个较低的地址。当函数返回时,它通过添加相同的数字(或通过从保存它的位置加载前一个堆栈指针值)来反转它。


这似乎已经包含了问题的答案。一个完美的例子和解释。我真的不明白问题是什么。

它为每个递归级别使用一堆激活帧。

我唯一看到的是你在进入递归调用和离开它时有 5。如果将其拆分为 5a 和 5b,就不会有任何不清楚的地方。

回答标题中的问题(与正文中的问题相反): char 变量存储在局部变量中,c作为局部变量,每次递归调用都存在一次;或多或少从 1 到 6。

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部