这个问题已得到广泛回答。请允许我使用更具教学性的方法加入一个额外的答案。
您可以将函数递归视为具有两个不同阶段的气泡堆栈:推动阶段和爆发阶段。
A) PUSHING STAGE(或“推栈”,正如 OP 所说)
0) 起始 Bubble #0 是 MAIN 函数。它被这些信息炸毁了:
- 局部变量。
- 对下一个 Bubble #1 的调用(第一次调用递归
函数,MYFUNC)。
1) Bubble #1 在轮到它时被以下信息炸毁:
- 上一个 Bubble #0 中的参数。
- 必要时使用局部变量。
- 返回地址。
- 使用返回值终止检查(例如:if (counter == 0) {return 1})。
- 调用下一个 Bubble #2。
请记住,这个气泡和其他气泡一样,是递归函数 MYFUNC。
2) Bubble #2 使用与 Bubble #1 相同的信息被炸毁,从后者获取必要的输入(参数)。在此之后,您可以根据需要堆叠任意数量的气泡,根据气泡 #1 中列出的项目相应地膨胀信息。
i) 因此,您可以得到任意数量的气泡:Bubble #3、Bubble #4...、Bubble #i。最后一个气泡在终止检查中有一个 NAIL。请注意!
B) BURSTING STAGE(或“弹出堆栈”,正如 OP 所说)
这个阶段发生在您达到肯定的终止检查并且包含钉子的最后一个气泡破裂时。
假设这个阶段发生在 Bubble #3 中。达到肯定的终止检查,并且 Bubble #3 破裂。然后从这个泡沫中解放出来的钉子。这颗钉子落在 Bubble #2 下方并将其爆裂。发生这种情况后,钉子会随着它的坠落而破裂,直到它爆破 Bubble #1。 Bubble #0 也是如此。重要的是要注意,钉子会跟随泡沫中的返回地址,此时它正在破裂:地址告诉钉子在坠落时要遵循的方向。
在这个过程结束时,得到答案并将其传递给 MAIN 函数(或 Bubble #0,当然不是爆裂)。
C) 以图形方式(按照 OP 的要求)
这是图形解释。它从底部,气泡 #0 到顶部,气泡 #3。
/*Bubble #3 (MYFUNC recursive function): Parameters from Bubble #2,
local variables, returning address, terminating check (NAIL),
call (not used here, as terminating check is positive).*/
向上推到上面的气泡 ↑ --------------------------------- -------------------- ? 钉子掉到泡泡#2
/*Bubble #2 (MYFUNC recursive function): Parameters from Bubble #1,
local variables, returning address, terminating check (not used),
call to Bubble #3.*/
向上推到上面的气泡 ↑ --------------------------------- -------------------- ? 钉子掉到泡泡#1
/*Bubble #1 (MYFUNC recursive function): Parameters from Bubble #0,
local variables, returning address, terminating check (not used),
call to Bubble #2.*/
向上推到上面的气泡 ↑ --------------------------------- -------------------- ? 钉子掉到泡泡#0
/*Bubble #0 (MAIN function): local variables, the first call to Bubble #1.*/
希望这种方法对某人有所帮助。如果需要任何澄清,请告诉我。