我很难抓住递归。例如,我有以下方法。当if语句返回true时,我希望从此方法返回。但是,查看Windbg和Visual Studio中的方法执行情况表明该方法继续执行。我为一般性问题道歉,但您的反馈意见真的很感激。
N如何按顺序递减以满足if条件?
long factorial(int N)
{
if(N == 1)
return 1;
return N * factorial(N - 1);
}
答案 0 :(得分:3)
编译和反汇编你应该得到类似于
的反汇编的函数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再次传递给函数事实(在没有返回调用者的情况下递归)循环再次发生,并且递减的N重新发送到事实这继续发生直到没有采用直到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
答案 1 :(得分:1)
我认为最好的方法是手动处理代码。假设您调用factorial(4),会发生什么?4不等于1.返回4 * factorial(4-1)。
阶乘3的回报值是多少? 3不等于1返回3 *阶乘(3-1)。
阶乘2的回报价值是多少? 2不等于1返回2 *阶乘(2-1)。
阶乘1的回报值是多少? 1等于1是真的。返回1.这是基本情况。现在我们重新开始递归。 返回1.这是因子(2-1) 返回2 * 1。这是阶乘(3-1) 返回3 * 2这是阶乘(4-1) 返回4 * 6这是因子(4),你做的原始电话。
这个想法是你有一个具有基本情况的函数(当n = 1返回1时)并且函数调用自身的方式将函数移向基本情况(factorial(n ** - ** 1)) 。