C 即使经过一个循环,递归如何保持值

C 即使经过一个循环,递归如何保持值,c,recursion,C,Recursion,有人能解释一下这个程序的执行情况吗。 输出为: 1. 2. 3. 4. 3. 2. 一, 函数最终如何保留值3,2,1 main(){ int h=0; g(h); } g(int n){ n++; printf("%d\n",n); if (n ==4)return 88; g(n); printf("%d\n",n); } 您获得上述输出是因为在代码的第8行,您正在递归地调用函数agian,因此第8行之后的剩余代码将保存在内存中的调用

有人能解释一下这个程序的执行情况吗。 输出为: 1. 2. 3. 4. 3. 2. 一,

函数最终如何保留值3,2,1

main(){
   int h=0;
    g(h);
}
 g(int n){
    n++;
    printf("%d\n",n);
    if (n ==4)return 88;
    g(n);
    printf("%d\n",n);
}

您获得上述输出是因为在代码的第8行,您正在递归地调用函数agian,因此第8行之后的剩余代码将保存在内存中的调用堆栈中。因此,当您获得输出1 2 3 4时,剩下的代码(在调用堆栈中)将被执行,因此您将获得此输出

下面是程序的调用堆栈 当n=0时,堆栈将放置1

|___|
|___|
|_1_|
当n=1时,堆栈将放置2

|___|
|_2_|
|_1_|
当n=2时,堆栈将放置3个

|_3_|
|_2_|
|_1_|
当n=4时,堆栈在遇到return语句时不会放置任何内容 现在,我们的堆栈中有一些值

因此,程序开始弹出堆栈中最顶层的值(此处n=3),并在其停止的位置继续执行(即,它将打印该值),该过程将继续,直到堆栈为空


注意:您可以访问此视频以更有效地了解递归

您将获得上述输出,因为在代码的第8行,您正在以递归方式调用函数,因此第8行之后的剩余代码将保存在内存中的调用堆栈中。因此,当您获得输出1 2 3 4时,剩下的代码(在调用堆栈中)将被执行,因此您将获得此输出

下面是程序的调用堆栈 当n=0时,堆栈将放置1

|___|
|___|
|_1_|
当n=1时,堆栈将放置2

|___|
|_2_|
|_1_|
当n=2时,堆栈将放置3个

|_3_|
|_2_|
|_1_|
当n=4时,堆栈在遇到return语句时不会放置任何内容 现在,我们的堆栈中有一些值

因此,程序开始弹出堆栈中最顶层的值(此处n=3),并在其停止的位置继续执行(即,它将打印该值),该过程将继续,直到堆栈为空


注意:您可以访问此视频以更有效地了解递归

在C中,函数参数充当函数内部的局部变量。此外,C使用按值调用,这意味着调用者用作参数的变量值被复制到函数参数变量中。因此,这两个变量是完全独立的变量

考虑以下代码:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int y)
{
    y++;
    printf("%d ", y);
    foo(y);
    printf("%d", y);
}

bar(0);
void recFun (int a) {
   if (a > 6)
       printf("%d\n", a);

   recFun (a + 1);

   printf("%d\n");
}
这将输出“1 2 1”

大多数人发现对
x
的更改显然不会改变
y
。它们是两个不同的变量。所以这并不奇怪

如果我们将代码更改为对变量使用相同的名称,例如:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int x)
{
    x++;
    printf("%d ", x);
    foo(x);
    printf("%d", x);
}

bar(0);
输出仍然是“1 2 1”

因为变量
x
inside
foo
x
inside
bar
之外的另一个变量。它们之间的唯一关系是
x
inside
foo
x
inside
bar
值的副本进行初始化。无论您对
x
inside
foo
进行何种更改,它都将/无法更改
x
inside
bar

递归也是如此。每个函数调用都创建自己的变量
n
——完全独立于以前调用中的
n
变量

大多数实现都使用堆栈来实现此功能。搜索“堆栈帧”以获取更多信息。也看到

在C语言中,函数参数充当函数内部的局部变量。此外,C使用按值调用,这意味着调用者用作参数的变量值被复制到函数参数变量中。因此,这两个变量是完全独立的变量

考虑以下代码:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int y)
{
    y++;
    printf("%d ", y);
    foo(y);
    printf("%d", y);
}

bar(0);
void recFun (int a) {
   if (a > 6)
       printf("%d\n", a);

   recFun (a + 1);

   printf("%d\n");
}
这将输出“1 2 1”

大多数人发现对
x
的更改显然不会改变
y
。它们是两个不同的变量。所以这并不奇怪

如果我们将代码更改为对变量使用相同的名称,例如:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int x)
{
    x++;
    printf("%d ", x);
    foo(x);
    printf("%d", x);
}

bar(0);
输出仍然是“1 2 1”

因为变量
x
inside
foo
x
inside
bar
之外的另一个变量。它们之间的唯一关系是
x
inside
foo
x
inside
bar
值的副本进行初始化。无论您对
x
inside
foo
进行何种更改,它都将/无法更改
x
inside
bar

递归也是如此。每个函数调用都创建自己的变量
n
——完全独立于以前调用中的
n
变量

大多数实现都使用堆栈来实现此功能。搜索“堆栈帧”以获取更多信息。也看到

你可以阅读上面的答案,它们都很好,但这里有另一种方法可以让你绕开它。最简单的答案是调用方函数在调用任何函数时保留其值的相同方式。例如,如果您有:

int main (void) {
    int a = 5;
    fun1 (a);
}

void fun1 (a) {
    fun2 (a);
    printf("%d\n", a); // output would be 5
}

void fun2 (int a) {
    a+=1;
    fun3 (a);
    printf("%d\n", a);
}

void fun3 (int a) {
    a+=1;
    printf("%d\n", a);
}
所以
fun1()
将打印出
5
fun2()
6
fun3()
7
。从调用方和被调用函数的角度来看,递归函数与上述类似,它不是使用不同的名称调用函数,而是使用相同的名称调用函数,或者换句话说,它是在调用自身

请看以下代码:

void foo(int x)
{
    x++;
    printf("%d", x);
}

void bar(int y)
{
    y++;
    printf("%d ", y);
    foo(y);
    printf("%d", y);
}

bar(0);
void recFun (int a) {
   if (a > 6)
       printf("%d\n", a);

   recFun (a + 1);

   printf("%d\n");
}
当我还在学校的时候,有些人会将上面的内容改写为以下内容(当然,如果你试图编译它,这会在一张纸上对你大喊大叫):


你可以阅读上面的答案,它们都很好,但这里有另一种方法让你了解它。最简单的ans