鱼C论坛

 找回密码
 立即注册
查看: 1842|回复: 9

[已解决]请老师指点,递归函数的变量用不用考虑作用域

[复制链接]
发表于 2018-7-10 21:26:52 | 显示全部楼层 |阅读模式
10鱼币
本帖最后由 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;
    }

结论就是递归函数里的变量当静态局部变量
最佳答案
2018-7-10 21:26:53
1.png

只要调用一次函数,就会有一个对象生成
可以看到这些变量n的地址不一样,也就是他们是不同的对象,只是名字相同而已

最佳答案

查看完整内容

只要调用一次函数,就会有一个对象生成 可以看到这些变量n的地址不一样,也就是他们是不同的对象,只是名字相同而已
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-10 21:26:53 | 显示全部楼层    本楼为最佳答案   
1.png

只要调用一次函数,就会有一个对象生成
可以看到这些变量n的地址不一样,也就是他们是不同的对象,只是名字相同而已
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-10 22:14:04 | 显示全部楼层
1.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-10 22:33:27 | 显示全部楼层

老师,我再想想
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-10 22:37:28 | 显示全部楼层

老师,32位汇编不用考虑ds寄存器段地址吧,sp,bp直接可以全内存指向
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-10 22:40:38 | 显示全部楼层
wow7jiao 发表于 2018-7-10 22:37
老师,32位汇编不用考虑ds寄存器段地址吧,sp,bp直接可以全内存指向

一般不需要
你现在就认为不需要就可以了
当你认为需要的时候,相信你已经在一个很高的高度了,那时你会有你自己的见解
^_^
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-11 02:46:31 | 显示全部楼层
这题目好玩,练习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;
}

n2.gif
搞定了。。
但是看见你一句:结论就是递归函数里的变量当静态局部变量
你这意思是如果咱们写死递归,溢出的原因一定是 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个字节。


QQ拼音截图20180711024041.png
啦啦啦看不懂这个反汇编
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-11 13:46:38 | 显示全部楼层
本帖最后由 人造人 于 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;
}
1.png
地址一样,这次这个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,[ebp-0C0h]  
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:[edi]  
        if(n)
00C8470E 83 7D 08 00          cmp         dword ptr [n],0  
00C84712 74 0F                je          Test+33h (0C84723h)  
                Test(n - 1);
00C84714 8B 45 08             mov         eax,dword ptr [n]  
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 [a (0C8A13Ch)]  
00C84728 83 C0 01             add         eax,1  
00C8472B A3 3C A1 C8 00       mov         dword ptr [a (0C8A13Ch)],eax  
        printf("%p -> %d\n", &a, a);
00C84730 A1 3C A1 C8 00       mov         eax,dword ptr [a (0C8A13Ch)]  
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,[ebp-0C0h]  
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:[edi]  
        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;
}
2.png
地址不一样,这些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,[ebp-0CCh]  
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:[edi]  
        if(n)
013D470E 83 7D 08 00          cmp         dword ptr [n],0  
013D4712 74 0F                je          Test+33h (013D4723h)  
                Test(n - 1);
013D4714 8B 45 08             mov         eax,dword ptr [n]  
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 [a],0  
        ++a;
013D472A 8B 45 F8             mov         eax,dword ptr [a]  
013D472D 83 C0 01             add         eax,1  
013D4730 89 45 F8             mov         dword ptr [a],eax  
        printf("%p -> %d\n", &a, a);
013D4733 8B 45 F8             mov         eax,dword ptr [a]  
013D4736 50                   push        eax  
013D4737 8D 4D F8             lea         ecx,[a]  
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:[13D4770h]  
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,[ebp-0C0h]  
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:[edi]  
        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  
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2018-7-11 13:50:44 | 显示全部楼层
去掉了"显示符号名"
        int a = 0;
013D4723 C7 45 F8 00 00 00 00 mov         dword ptr [ebp-8],0  
        ++a;
013D472A 8B 45 F8             mov         eax,dword ptr [ebp-8]  
013D472D 83 C0 01             add         eax,1  
013D4730 89 45 F8             mov         dword ptr [ebp-8],eax  
        printf("%p -> %d\n", &a, a);
013D4733 8B 45 F8             mov         eax,dword ptr [ebp-8]  
013D4736 50                   push        eax  
013D4737 8D 4D F8             lea         ecx,[ebp-8]  
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:[000DA13Ch]  
000D4728 83 C0 01             add         eax,1  
000D472B A3 3C A1 0D 00       mov         dword ptr ds:[000DA13Ch],eax  
        printf("%p -> %d\n", &a, a);
000D4730 A1 3C A1 0D 00       mov         eax,dword ptr ds:[000DA13Ch]  
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  
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2018-7-11 15:18:26 | 显示全部楼层
本帖最后由 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;
}



地址是对称的,值不对称
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-30 02:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表