鱼C论坛

 找回密码
 立即注册
查看: 2017|回复: 19

[已解决]关于c语言递归的一个问题

[复制链接]
发表于 2019-3-8 21:00:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include <stdio.h>
int a(int n)
{
    int p;
    if(n==2)
        {
            return n;
        }
    else
    {

        a(n-1);
        p=n*n;
    }
}
int main(int argc, char const *argv[])
{
    /* code */
    printf("%d\n",a(5) );
    return 0;
}
这个返回值是多少呢?
最佳答案
2019-3-9 14:15:18
本帖最后由 Croper 于 2019-3-9 14:16 编辑

部分反汇编的结果:
#include <stdio.h>
int a(int n)
{
    int p;
    if(n==2)
        {
            return n;
        }
    else
    {

        a(n-1);
        p=n*n;
//这是最后一次使用eax寄存器的位置
//01101814  mov         eax,dword ptr [n]     //把n的值放入eax寄存器,此时eax=5
//01101817  imul        eax,dword ptr [n]      //eax寄存器的乘上n的值,此时eax=25
//0110181B  mov         dword ptr [p],eax    //把eax寄存器的值放入p,此时p=25,eax=25;
    }
}
int main(int argc, char const *argv[])
{
    /* code */
    printf("%d\n",a(5) );
//01101988  push        5  
//0110198A  call        a (01101217h)   //这是调用函数a,返回后eax=25
//0110198F  add         esp,4      
//01101992  push        eax     //把eax当做a()的返回值推入栈,此时eax=25
//01101993  push        offset string "%d\n" (01107B30h)  
//01101998  call        _printf (0110104Bh)        //调用printf,此时输出的值当然是25
//0110199D  add         esp,8  
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-3-8 21:16:36 | 显示全部楼层
本帖最后由 jackz007 于 2019-3-8 21:22 编辑

      楼主的函数 a() 存在重大问题,只有在 n == 2 时才有返回值,n == 5 的时候无返回值。在递归过程中,返回值没有得到任何利用,也无法影响最终结果,根本没有必要使用递归函数。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-8 21:20:45 | 显示全部楼层
25,这种编译运行一下不就行了嘛
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-8 21:28:12 | 显示全部楼层
唉,好像不对吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-8 22:02:22 | 显示全部楼层
你在p = n*n后面加上printf("%d\n",p);
产生了新的数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-8 22:05:24 | 显示全部楼层
暗pluto 发表于 2019-3-8 22:02
你在p = n*n后面加上printf("%d\n",p);
产生了新的数

我就想知道这个返回值为什么是25,我函数里面没有return p啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-8 22:06:08 | 显示全部楼层
jackz007 发表于 2019-3-8 21:16
楼主的函数 a() 存在重大问题,只有在 n == 2 时才有返回值,n == 5 的时候无返回值。在递归过程中, ...

我知道递归怎么用,上面的程序是我偶然发现的一个问题
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-8 22:06:41 | 显示全部楼层
暗pluto 发表于 2019-3-8 21:20
25,这种编译运行一下不就行了嘛

为什么是25呢?解释一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-8 22:25:23 | 显示全部楼层
lcl1026504480 发表于 2019-3-8 22:06
为什么是25呢?解释一下

有单步调试过没有
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-8 23:39:16 From FishC Mobile | 显示全部楼层
p又没随n变化 递归回来不是5*5吗
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-9 01:11:14 | 显示全部楼层
本帖最后由 暗pluto 于 2019-3-9 01:13 编辑
lcl1026504480 发表于 2019-3-8 22:06
为什么是25呢?解释一下


我单步调试了一下,发现非常有趣
大致的原因应该是这样的,你return n是没错,但是return n不代表终止递归,而是终止本层递归
所以你return后,会返回上一层的递归,而25正是最后退出递归的值,至于为什么n的值会被p所覆盖,这个我也不太清楚(如果清楚了请务必告诉我),修改正确后的代码如下
#include <stdio.h>
int flag = 0;
int a(int n)
{
    int p;
    if(n==2&&flag==0)
        {
            flag = 1;
            return n;
        }
    else{
        a(n-1);
        return;
        p = n*n;
    }
}
int main(int argc, char const *argv[])
{
    /* code */

    printf("%d",a(5));
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 11:42:53 | 显示全部楼层
lijialijialijia 发表于 2019-3-8 23:39
p又没随n变化 递归回来不是5*5吗

我return的是p吗?你有脑子吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 11:47:26 | 显示全部楼层
暗pluto 发表于 2019-3-9 01:11
我单步调试了一下,发现非常有趣
大致的原因应该是这样的,你return n是没错,但是return n不代表终止 ...

我也不知道为什么会覆盖,这个估计只有反汇编才能知道了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 11:50:38 | 显示全部楼层
lcl1026504480 发表于 2019-3-9 11:47
我也不知道为什么会覆盖,这个估计只有反汇编才能知道了

如果递归的下面的表达式或者语句不含有n,那么就是返回2,如果有关于n的操作,返回的就不是2.很奇怪
TIM图片20190309114854.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-9 11:56:46 | 显示全部楼层
为什么不是2?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 12:05:03 | 显示全部楼层
Swarm 发表于 2019-3-9 11:56
为什么不是2?

不知道啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 12:06:44 | 显示全部楼层
#include <stdio.h>
int a(int n)
{
    int p;
    if(n==2)
        {
            return n;
        }
    else
    {
        a(2);
        printf("abc%d\n",n*n );
    }
}
int main(int argc, char const *argv[])
{
    /* code */
    printf("%d\n",a(5) );
    return 0;
}

                               
登录/注册后可看大图

这个更迷
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 12:09:03 | 显示全部楼层
@小甲鱼 快来回答啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-3-9 14:15:18 | 显示全部楼层    本楼为最佳答案   
本帖最后由 Croper 于 2019-3-9 14:16 编辑

部分反汇编的结果:
#include <stdio.h>
int a(int n)
{
    int p;
    if(n==2)
        {
            return n;
        }
    else
    {

        a(n-1);
        p=n*n;
//这是最后一次使用eax寄存器的位置
//01101814  mov         eax,dword ptr [n]     //把n的值放入eax寄存器,此时eax=5
//01101817  imul        eax,dword ptr [n]      //eax寄存器的乘上n的值,此时eax=25
//0110181B  mov         dword ptr [p],eax    //把eax寄存器的值放入p,此时p=25,eax=25;
    }
}
int main(int argc, char const *argv[])
{
    /* code */
    printf("%d\n",a(5) );
//01101988  push        5  
//0110198A  call        a (01101217h)   //这是调用函数a,返回后eax=25
//0110198F  add         esp,4      
//01101992  push        eax     //把eax当做a()的返回值推入栈,此时eax=25
//01101993  push        offset string "%d\n" (01107B30h)  
//01101998  call        _printf (0110104Bh)        //调用printf,此时输出的值当然是25
//0110199D  add         esp,8  
    return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-3-9 14:38:46 | 显示全部楼层
Croper 发表于 2019-3-9 14:15
部分反汇编的结果:

这个我也反汇编过,不过感觉其实挺迷的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-10-3 10:39

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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