lcl1026504480 发表于 2019-3-8 21:00:44

关于c语言递归的一个问题

#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;
}
这个返回值是多少呢?

jackz007 发表于 2019-3-8 21:16:36

本帖最后由 jackz007 于 2019-3-8 21:22 编辑

      楼主的函数 a() 存在重大问题,只有在 n == 2 时才有返回值,n == 5 的时候无返回值。在递归过程中,返回值没有得到任何利用,也无法影响最终结果,根本没有必要使用递归函数。

暗pluto 发表于 2019-3-8 21:20:45

25,这种编译运行一下不就行了嘛

暗pluto 发表于 2019-3-8 21:28:12

唉,好像不对吧

暗pluto 发表于 2019-3-8 22:02:22

你在p = n*n后面加上printf("%d\n",p);
产生了新的数

lcl1026504480 发表于 2019-3-8 22:05:24

暗pluto 发表于 2019-3-8 22:02
你在p = n*n后面加上printf("%d\n",p);
产生了新的数

我就想知道这个返回值为什么是25,我函数里面没有return p啊

lcl1026504480 发表于 2019-3-8 22:06:08

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

我知道递归怎么用,上面的程序是我偶然发现的一个问题

lcl1026504480 发表于 2019-3-8 22:06:41

暗pluto 发表于 2019-3-8 21:20
25,这种编译运行一下不就行了嘛

为什么是25呢?解释一下

暗pluto 发表于 2019-3-8 22:25:23

lcl1026504480 发表于 2019-3-8 22:06
为什么是25呢?解释一下

有单步调试过没有

lijialijialijia 发表于 2019-3-8 23:39:16

p又没随n变化 递归回来不是5*5吗

暗pluto 发表于 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;
}

lcl1026504480 发表于 2019-3-9 11:42:53

lijialijialijia 发表于 2019-3-8 23:39
p又没随n变化 递归回来不是5*5吗

我return的是p吗?你有脑子吗?

lcl1026504480 发表于 2019-3-9 11:47:26

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

我也不知道为什么会覆盖,这个估计只有反汇编才能知道了

lcl1026504480 发表于 2019-3-9 11:50:38

lcl1026504480 发表于 2019-3-9 11:47
我也不知道为什么会覆盖,这个估计只有反汇编才能知道了

如果递归的下面的表达式或者语句不含有n,那么就是返回2,如果有关于n的操作,返回的就不是2.很奇怪

Swarm 发表于 2019-3-9 11:56:46

为什么不是2?

lcl1026504480 发表于 2019-3-9 12:05:03

Swarm 发表于 2019-3-9 11:56
为什么不是2?

不知道啊

lcl1026504480 发表于 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;
}
https://i0.hdslb.com/bfs/article/da7b04574ea194146b75594574e4826603d7eaf7.png
这个更迷

lcl1026504480 发表于 2019-3-9 12:09:03

@小甲鱼 快来回答啊

Croper 发表于 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寄存器的位置
//01101814mov         eax,dword ptr    //把n的值放入eax寄存器,此时eax=5
//01101817imul      eax,dword ptr       //eax寄存器的乘上n的值,此时eax=25
//0110181Bmov         dword ptr ,eax    //把eax寄存器的值放入p,此时p=25,eax=25;
    }
}
int main(int argc, char const *argv[])
{
    /* code */
    printf("%d\n",a(5) );
//01101988push      5
//0110198Acall      a (01101217h)   //这是调用函数a,返回后eax=25
//0110198Fadd         esp,4      
//01101992push      eax   //把eax当做a()的返回值推入栈,此时eax=25
//01101993push      offset string "%d\n" (01107B30h)
//01101998call      _printf (0110104Bh)      //调用printf,此时输出的值当然是25
//0110199Dadd         esp,8
    return 0;
}

lcl1026504480 发表于 2019-3-9 14:38:46

Croper 发表于 2019-3-9 14:15
部分反汇编的结果:

这个我也反汇编过,不过感觉其实挺迷的
页: [1]
查看完整版本: 关于c语言递归的一个问题