我很难掌握递归。例如我有以下方法。当 if 语句返回 true 时,我期望从此方法返回。然而,查看 Windbg 和 Visual Studio 中的方法执行情况表明该方法继续执行。对于这个一般性问题,我深表歉意,但我们将非常感谢您的反馈。
N 如何递减以满足 if 条件?
long factorial(int N)
{
if(N == 1)
return 1;
return N * factorial(N - 1);
}
最佳答案
编译和反汇编该函数,您应该得到与此类似的反汇编
0:000> cdb: Reading initial command 'uf fact!fact;q'
fact!fact:
00401000 55 push ebp
00401001 8bec mov ebp,esp
00401003 837d0801 cmp dword ptr [ebp+8],1
00401007 7507 jne fact!fact+0x10 (00401010)
fact!fact+0x9:
00401009 b801000000 mov eax,1
0040100e eb13 jmp fact!fact+0x23 (00401023)
fact!fact+0x10:
00401010 8b4508 mov eax,dword ptr [ebp+8]
00401013 83e801 sub eax,1
00401016 50 push eax
00401017 e8e4ffffff call fact!fact (00401000)
0040101c 83c404 add esp,4
0040101f 0faf4508 imul eax,dword ptr [ebp+8]
fact!fact+0x23:
00401023 5d pop ebp
00401024 c3 ret
quit:
当输入函数时,假设 N == 5,即 [ebp+8] 将保留 5 只要 [ebp+8] > 1 就会采用 jne
在这里你可以看到 N 被递减(sub eax ,1) 递减的 N 再次传递给函数fact(递归而不返回调用者)循环再次发生,递减的 N 被重新发送到fact,这种情况持续发生,直到 jne 未被采用,即直到 N 或 [ebp+8 ] == 1
当N变为1时,不取jne,但取jmp 401023 它返回给调用者,调用者是函数fact(int N)
也就是说,它将返回 40101c,其中发生 eax 的乘法,并将结果存储回 eax 中;
这将继续发生,直到 ret 指向 main() 中的第一次调用,然后在第一次执行 pop ebp 之前查看下面的堆栈
0:000> kPL
ChildEBP RetAddr
0013ff38 0040101c fact!fact(
int N = 0n1)+0x23
0013ff44 0040101c fact!fact(
int N = 0n2)+0x1c
0013ff50 0040101c fact!fact(
int N = 0n3)+0x1c
0013ff5c 0040101c fact!fact(
int N = 0n4)+0x1c
0013ff68 0040109f fact!fact(
int N = 0n5)+0x1c
0013ff78 0040140b fact!main(
int argc = 0n2,
char ** argv = 0x00033ac0)+0x6f
关于visual-studio-2010 - 递归方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28756199/