请老师指点,递归函数的变量用不用考虑作用域
本帖最后由 wow7jiao 于 2018-7-10 21:33 编辑输入5,打印结果:5 4 3 2 1 0 0 0 1 2 3 4
-------------------------------------------------------------------------
#include <stdio.h>
void up_and_down(int n);
void up_and_down(int n)
{
printf("%d ", n);<------;例如这里是5
if (n > 0)
{
up_and_down(--n);<----------这里的--n是不用考虑局部代码块
}
printf("%d ", n);<到这里这条语句,就是n = n -1 = 5 - 1 =4(如果考虑代码块作用域,这里应该还是5,上一个代码块的--n对这里没有影响)
}
int main(void)
{
int n;
printf("请输入一个整数:");
scanf("%d", &n);
up_and_down(n);
putchar('\n');
return 0;
}
结论就是递归函数里的变量当静态局部变量
只要调用一次函数,就会有一个对象生成
可以看到这些变量n的地址不一样,也就是他们是不同的对象,只是名字相同而已
人造人 发表于 2018-7-10 22:14
老师,我再想想 人造人 发表于 2018-7-10 22:14
老师,32位汇编不用考虑ds寄存器段地址吧,sp,bp直接可以全内存指向 wow7jiao 发表于 2018-7-10 22:37
老师,32位汇编不用考虑ds寄存器段地址吧,sp,bp直接可以全内存指向
一般不需要
你现在就认为不需要就可以了
当你认为需要的时候,相信你已经在一个很高的高度了,那时你会有你自己的见解
^_^
这题目好玩,练习ing
#include <stdio.h>
//5 4 3 2 1 0 0 0 1 2 3 4
void print(int n){
if(n>0){
printf("%d ",n);
print(--n);
}else{
printf("%d ",n);
}
printf("%d ",n);
}
int main(){
print(5);
return 0;
}
搞定了。。
但是看见你一句:结论就是递归函数里的变量当静态局部变量
你这意思是如果咱们写死递归,溢出的原因一定是 push print 的值。或者说溢出的原因一定不是由 int n 引起的
我记得没错的话,静态局部变量 == static int ,就算你循环调用 这个变量也不会进行压栈操作
刚看了8086汇编,推测一下反汇编,用了vs2015也没看明白
1.push ebp
2.mob ebp,esp
3.sub esp,8
4.push n
5.push print
....
每次调用函数都会执行以上5步,分配8个字节。
静态的话我想应该是这样
1.push ebp
2.mob ebp,esp
3.sub esp,4
4.push print
....
每次调用函数都会执行以上4步,分配4个字节。
啦啦啦看不懂这个反汇编
本帖最后由 人造人 于 2018-7-11 13:48 编辑
那我也来玩玩汇编语言
#include <stdio.h>
void Test(int n)
{
if(n)
Test(n - 1);
static int a = 0;
++a;
printf("%p -> %d\n", &a, a);
}
int main(void)
{
Test(5);
return 0;
}
地址一样,这次这个a是同一个a
void Test(int n)
{
00C846F0 55 push ebp
00C846F1 8B EC mov ebp,esp
00C846F3 81 EC C0 00 00 00 sub esp,0C0h
00C846F9 53 push ebx
00C846FA 56 push esi
00C846FB 57 push edi
00C846FC 8D BD 40 FF FF FF lea edi,
00C84702 B9 30 00 00 00 mov ecx,30h
00C84707 B8 CC CC CC CC mov eax,0CCCCCCCCh
00C8470C F3 AB rep stos dword ptr es:
if(n)
00C8470E 83 7D 08 00 cmp dword ptr ,0
00C84712 74 0F je Test+33h (0C84723h)
Test(n - 1);
00C84714 8B 45 08 mov eax,dword ptr
00C84717 83 E8 01 sub eax,1
00C8471A 50 push eax
00C8471B E8 73 CC FF FF call _Test (0C81393h)
00C84720 83 C4 04 add esp,4
static int a = 0;
++a;
00C84723 A1 3C A1 C8 00 mov eax,dword ptr
00C84728 83 C0 01 add eax,1
00C8472B A3 3C A1 C8 00 mov dword ptr ,eax
printf("%p -> %d\n", &a, a);
00C84730 A1 3C A1 C8 00 mov eax,dword ptr
00C84735 50 push eax
00C84736 68 3C A1 C8 00 push offset a (0C8A13Ch)
00C8473B 68 F0 7B C8 00 push offset string "%p -> %d\n" (0C87BF0h)
00C84740 E8 EF CB FF FF call _printf (0C81334h)
00C84745 83 C4 0C add esp,0Ch
}
00C84748 5F pop edi
00C84749 5E pop esi
00C8474A 5B pop ebx
00C8474B 81 C4 C0 00 00 00 add esp,0C0h
00C84751 3B EC cmp ebp,esp
00C84753 E8 D4 C9 FF FF call __RTC_CheckEsp (0C8112Ch)
00C84758 8B E5 mov esp,ebp
00C8475A 5D pop ebp
00C8475B C3 ret
int main(void)
{
00C81790 55 push ebp
00C81791 8B EC mov ebp,esp
00C81793 81 EC C0 00 00 00 sub esp,0C0h
00C81799 53 push ebx
00C8179A 56 push esi
00C8179B 57 push edi
00C8179C 8D BD 40 FF FF FF lea edi,
00C817A2 B9 30 00 00 00 mov ecx,30h
00C817A7 B8 CC CC CC CC mov eax,0CCCCCCCCh
00C817AC F3 AB rep stos dword ptr es:
Test(5);
00C817AE 6A 05 push 5
00C817B0 E8 DE FB FF FF call _Test (0C81393h)
00C817B5 83 C4 04 add esp,4
return 0;
00C817B8 33 C0 xor eax,eax
}
00C817BA 5F pop edi
00C817BB 5E pop esi
00C817BC 5B pop ebx
00C817BD 81 C4 C0 00 00 00 add esp,0C0h
00C817C3 3B EC cmp ebp,esp
00C817C5 E8 62 F9 FF FF call __RTC_CheckEsp (0C8112Ch)
00C817CA 8B E5 mov esp,ebp
00C817CC 5D pop ebp
00C817CD C3 ret
#include <stdio.h>
void Test(int n)
{
if(n)
Test(n - 1);
int a = 0;
++a;
printf("%p -> %d\n", &a, a);
}
int main(void)
{
Test(5);
return 0;
}
地址不一样,这些a都是不同的对象,只是名字相同而已
void Test(int n)
{
013D46F0 55 push ebp
013D46F1 8B EC mov ebp,esp
013D46F3 81 EC CC 00 00 00 sub esp,0CCh
013D46F9 53 push ebx
013D46FA 56 push esi
013D46FB 57 push edi
013D46FC 8D BD 34 FF FF FF lea edi,
013D4702 B9 33 00 00 00 mov ecx,33h
013D4707 B8 CC CC CC CC mov eax,0CCCCCCCCh
013D470C F3 AB rep stos dword ptr es:
if(n)
013D470E 83 7D 08 00 cmp dword ptr ,0
013D4712 74 0F je Test+33h (013D4723h)
Test(n - 1);
013D4714 8B 45 08 mov eax,dword ptr
013D4717 83 E8 01 sub eax,1
013D471A 50 push eax
013D471B E8 73 CC FF FF call _Test (013D1393h)
013D4720 83 C4 04 add esp,4
int a = 0;
013D4723 C7 45 F8 00 00 00 00 mov dword ptr ,0
++a;
013D472A 8B 45 F8 mov eax,dword ptr
013D472D 83 C0 01 add eax,1
013D4730 89 45 F8 mov dword ptr ,eax
printf("%p -> %d\n", &a, a);
013D4733 8B 45 F8 mov eax,dword ptr
013D4736 50 push eax
013D4737 8D 4D F8 lea ecx,
013D473A 51 push ecx
013D473B 68 F0 7B 3D 01 push offset string "%p -> %d\n" (013D7BF0h)
013D4740 E8 EF CB FF FF call _printf (013D1334h)
013D4745 83 C4 0C add esp,0Ch
}
013D4748 52 push edx
}
013D4749 8B CD mov ecx,ebp
013D474B 50 push eax
013D474C 8D 15 70 47 3D 01 lea edx,ds:
013D4752 E8 15 CB FF FF call @_RTC_CheckStackVars@8 (013D126Ch)
013D4757 58 pop eax
013D4758 5A pop edx
013D4759 5F pop edi
013D475A 5E pop esi
013D475B 5B pop ebx
013D475C 81 C4 CC 00 00 00 add esp,0CCh
013D4762 3B EC cmp ebp,esp
013D4764 E8 C3 C9 FF FF call __RTC_CheckEsp (013D112Ch)
013D4769 8B E5 mov esp,ebp
013D476B 5D pop ebp
013D476C C3 ret
int main(void)
{
013D1790 55 push ebp
013D1791 8B EC mov ebp,esp
013D1793 81 EC C0 00 00 00 sub esp,0C0h
013D1799 53 push ebx
013D179A 56 push esi
013D179B 57 push edi
013D179C 8D BD 40 FF FF FF lea edi,
013D17A2 B9 30 00 00 00 mov ecx,30h
013D17A7 B8 CC CC CC CC mov eax,0CCCCCCCCh
013D17AC F3 AB rep stos dword ptr es:
Test(5);
013D17AE 6A 05 push 5
013D17B0 E8 DE FB FF FF call _Test (013D1393h)
013D17B5 83 C4 04 add esp,4
return 0;
013D17B8 33 C0 xor eax,eax
}
013D17BA 5F pop edi
013D17BB 5E pop esi
013D17BC 5B pop ebx
013D17BD 81 C4 C0 00 00 00 add esp,0C0h
013D17C3 3B EC cmp ebp,esp
013D17C5 E8 62 F9 FF FF call __RTC_CheckEsp (013D112Ch)
013D17CA 8B E5 mov esp,ebp
013D17CC 5D pop ebp
013D17CD C3 ret
去掉了"显示符号名"
int a = 0;
013D4723 C7 45 F8 00 00 00 00 mov dword ptr ,0
++a;
013D472A 8B 45 F8 mov eax,dword ptr
013D472D 83 C0 01 add eax,1
013D4730 89 45 F8 mov dword ptr ,eax
printf("%p -> %d\n", &a, a);
013D4733 8B 45 F8 mov eax,dword ptr
013D4736 50 push eax
013D4737 8D 4D F8 lea ecx,
013D473A 51 push ecx
013D473B 68 F0 7B 3D 01 push 13D7BF0h
013D4740 E8 EF CB FF FF call 013D1334
013D4745 83 C4 0C add esp,0Ch
static int a = 0;
++a;
000D4723 A1 3C A1 0D 00 mov eax,dword ptr ds:
000D4728 83 C0 01 add eax,1
000D472B A3 3C A1 0D 00 mov dword ptr ds:,eax
printf("%p -> %d\n", &a, a);
000D4730 A1 3C A1 0D 00 mov eax,dword ptr ds:
000D4735 50 push eax
000D4736 68 3C A1 0D 00 push 0DA13Ch
000D473B 68 F0 7B 0D 00 push 0D7BF0h
000D4740 E8 EF CB FF FF call 000D1334
000D4745 83 C4 0C add esp,0Ch 本帖最后由 wow7jiao 于 2018-7-11 15:21 编辑
#include <stdio.h>
//5 4 3 2 1 0 0 0 1 2 3 4
void up_and_down(int n);
void up_and_down(int n)
{
printf("%p -> %d\n", &n, n);
if(n > 0)
{
up_and_down(--n);
}
printf("%p -> %d\n", &n, n);
}
int main(void)
{
int n;
printf("请输入一个整数");
scanf("%d", &n);
up_and_down(n);
putchar("\n");
return 0;
}
地址是对称的,值不对称
页:
[1]