请解释这个C程序的工作原理
Please explain the working of this C program
#include<stdio.h>
void func1(int n)
{
if(n==0) return;
printf("%d",n);
func2(n-2);
printf("%d",n);
}
void func2(int n)
{
if(n==0) return;
printf("%d",n);
func1(++n);
printf("%d",n);
}
void main()
{
func1(5);
}
输出:53423122233445
我不明白导致上述输出的代码中发生的控制流。有人可以解释一下吗?提前谢谢你:)
如果我们对每个 printf
进行注释,这将变得更容易理解,这样我们就可以分辨出哪个数字来自程序的哪个部分。我还将开始条件更改为 3,这样我们就可以完成整个过程。
#include <stdio.h>
void func2(int);
void func1(int n)
{
if(n==0) return;
printf("func1 before: %d\n",n);
func2(n-2);
printf("func1 after: %d\n",n);
}
void func2(int n)
{
if(n==0) return;
printf("func2 before: %d\n",n);
func1(++n);
printf("func2 after: %d\n",n);
}
int main()
{
func1(3);
}
产生:
func1 before: 3
func2 before: 1
func1 before: 2
func1 after: 2
func2 after: 2
func1 after: 3
- func1(3) 打印 3 并调用 func2(1)。
- func2(1) 打印 1 并调用 func1(2)。
- func1(2) 打印 2 个调用 func2(0)。
- func2(0) returns 立即。
现在我们已经到达了递归的底部。至此,我们已经建立了一堆函数调用。
- func1(3)
- func2(1)
- func1(2)
一旦 func2(0) returns,对 func1(2) 的调用从它停止的地方开始,我们从下往上处理堆栈。
- func1(2) 打印 2 和 returns 到 func2(1)。
- func2(1) 打印 2,因为它增加了 n,并且 returns 到 func1(3)。
- func1(3) 打印 3 和 returns 到 main()。
- main() returns 程序退出。
我通过教学生递归如何与局部变量一起工作,我发现理解它的最简单方法是,如果你完全按照计算机的方式去做,
- 逐步处理它,并记下调用的内容以及变量值何时更改
例如:
main
func1(5)
n=5
printf 5
func2(5-2)
n=3
print 3
++n
n=4
func1(4)
n=4
print 4
func2(4-2)
n=2
print 2
++n
n=3
func1(3)
n=3
print 3
func2(3-2)
n=1
print 1
++n
n=2
func1(2)
n=2
print 2
func2(2-2)
n=0
if n==0 => return
print 2
print 2
print 3
print 3
print 4
print 4
print 5
//done
您还需要了解,在每个函数调用中,
函数内对 'n' 的更改不会更改较早的
调用位置的值。
如果你想象计算机正在做这样的事情,你会看得更清楚:
每个函数调用都会在堆栈上创建一组新变量,
当函数 returns 时,它的变量从堆栈中删除。
stack: (empty)
main
func1(5) ==> push n='5' on stack, then jump to func1()
stack is now { n=5 }
so n is 5
print 5
func2(5-2) ==> push 'n=3' on stack, then jump to func2()
stack is now { n=3 } , { n=5 }
so n is 3
print 3
++n
stack is now { n=4 } , { n=5 }
func1(4) ==> push 'n=4' on stack then jump to func1()
stack is now { n=4} , { n=4 } , { n=5 }
so n is 4
print 4
func2(4-2) ==> push 'n=2' on stack then jump to func()
stack is now {n=2}, {n=4} , { n=4 } , { n=5 }
++n
stack is now {n=3}, {n=4} , { n=4 } , { n=5 }
...etc...
.....
....
stack is eventually {n=0} {n=2}, {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
after func(2-2) is called
then:
if n==0 => return;
the return pops one item {n=0} off the stack, so
stack is then {n=2}, {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 2
return (deletes {n=2})
stack is then {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 2
return (deletes {n=2})
stack is then {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 2
return (deletes {n=2})
stack is then {n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 1
return (deletes {n=1})
stack is then {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 3
依此类推,直到完成并打印出最后一个“5”。
#include<stdio.h>
void func1(int n)
{
if(n==0) return;
printf("%d",n);
func2(n-2);
printf("%d",n);
}
void func2(int n)
{
if(n==0) return;
printf("%d",n);
func1(++n);
printf("%d",n);
}
void main()
{
func1(5);
}
输出:53423122233445
我不明白导致上述输出的代码中发生的控制流。有人可以解释一下吗?提前谢谢你:)
如果我们对每个 printf
进行注释,这将变得更容易理解,这样我们就可以分辨出哪个数字来自程序的哪个部分。我还将开始条件更改为 3,这样我们就可以完成整个过程。
#include <stdio.h>
void func2(int);
void func1(int n)
{
if(n==0) return;
printf("func1 before: %d\n",n);
func2(n-2);
printf("func1 after: %d\n",n);
}
void func2(int n)
{
if(n==0) return;
printf("func2 before: %d\n",n);
func1(++n);
printf("func2 after: %d\n",n);
}
int main()
{
func1(3);
}
产生:
func1 before: 3
func2 before: 1
func1 before: 2
func1 after: 2
func2 after: 2
func1 after: 3
- func1(3) 打印 3 并调用 func2(1)。
- func2(1) 打印 1 并调用 func1(2)。
- func1(2) 打印 2 个调用 func2(0)。
- func2(0) returns 立即。
现在我们已经到达了递归的底部。至此,我们已经建立了一堆函数调用。
- func1(3)
- func2(1)
- func1(2)
一旦 func2(0) returns,对 func1(2) 的调用从它停止的地方开始,我们从下往上处理堆栈。
- func1(2) 打印 2 和 returns 到 func2(1)。
- func2(1) 打印 2,因为它增加了 n,并且 returns 到 func1(3)。
- func1(3) 打印 3 和 returns 到 main()。
- main() returns 程序退出。
我通过教学生递归如何与局部变量一起工作,我发现理解它的最简单方法是,如果你完全按照计算机的方式去做, - 逐步处理它,并记下调用的内容以及变量值何时更改
例如:
main
func1(5)
n=5
printf 5
func2(5-2)
n=3
print 3
++n
n=4
func1(4)
n=4
print 4
func2(4-2)
n=2
print 2
++n
n=3
func1(3)
n=3
print 3
func2(3-2)
n=1
print 1
++n
n=2
func1(2)
n=2
print 2
func2(2-2)
n=0
if n==0 => return
print 2
print 2
print 3
print 3
print 4
print 4
print 5
//done
您还需要了解,在每个函数调用中, 函数内对 'n' 的更改不会更改较早的 调用位置的值。
如果你想象计算机正在做这样的事情,你会看得更清楚: 每个函数调用都会在堆栈上创建一组新变量, 当函数 returns 时,它的变量从堆栈中删除。
stack: (empty)
main
func1(5) ==> push n='5' on stack, then jump to func1()
stack is now { n=5 }
so n is 5
print 5
func2(5-2) ==> push 'n=3' on stack, then jump to func2()
stack is now { n=3 } , { n=5 }
so n is 3
print 3
++n
stack is now { n=4 } , { n=5 }
func1(4) ==> push 'n=4' on stack then jump to func1()
stack is now { n=4} , { n=4 } , { n=5 }
so n is 4
print 4
func2(4-2) ==> push 'n=2' on stack then jump to func()
stack is now {n=2}, {n=4} , { n=4 } , { n=5 }
++n
stack is now {n=3}, {n=4} , { n=4 } , { n=5 }
...etc...
.....
....
stack is eventually {n=0} {n=2}, {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
after func(2-2) is called
then:
if n==0 => return;
the return pops one item {n=0} off the stack, so
stack is then {n=2}, {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 2
return (deletes {n=2})
stack is then {n=2}, {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 2
return (deletes {n=2})
stack is then {n=2} ,{n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 2
return (deletes {n=2})
stack is then {n=1} {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 1
return (deletes {n=1})
stack is then {n=3}, {n=3}, {n=4} , { n=4 } , { n=5 }
print 3
依此类推,直到完成并打印出最后一个“5”。