关闭

递归函数内部的原理????不要跟我讲自己调用自己这样的话,我一分也不给你的zz

2437人阅读 评论(0) 收藏 举报
楼主wormemory(绿茶)2002-06-13 12:52:41 在 C/C++ / C语言 提问
递归函数内部的原理????不要跟我讲自己调用自己这样的话,我一分也不给你的,  
  我要知道的是,系统是不是一定会建一个栈区,或者说为什么一定要建栈,系统是怎么来实现的,或者说系统是根据什么来建栈,他(系统)怎么会知道我那个就是递归函数而不是其他什么东西之类,系统是怎么实现的,每一部是怎么实现的  
  强调,我要知道的是内部是怎么实现的 问题点数:100、回复次数:13

1 楼lonk(寂寞低手·小渝)回复于 2002-06-13 13:23:32 得分 15

内部原理的话,其实和一般的函数调用是一样的.  
  一般在函数A(a,b)内部调用一个函数B(c,d)时,把B的参数往栈上压,  
   
  d   <--栈指针           就变成左边的样子,如果在B内部再调用一个函数C,也是  
  ---                           类似做法,压参数,栈指针上移等到B执行完毕,就做弹栈的  
  c                               操作,也就是指针下移,回到执行点而已.  
  ---                           而递归的做法没什么两样,在A中调用A也是重复上面的过程  
  ---                           ,压栈,压栈,压栈,然后再弹栈,弹栈,弹栈.根本不要额外  
  A的其它                   判断什么东西.  
  参数                         最后要补充的,就是在可能还在栈里放一个参数来记住  
  ---                           从函数返回的时候,栈指针要指向哪里.  
  b  
  ---  
  aTop

2 楼richard_hu(华仔)回复于 2002-06-13 13:25:10 得分 15

系统不会去考虑你是不是递归还是什么的,他还没高级到这个程度。只是按照结构化的顺序执行下去的时候,比如在主函数理当调用一个函数的时候,系统自 动开辟一个栈空间,存入函数头(以便返回值),形参,以及ip(以便返回式继续执行),然后跳转至该函数去执行,但执行完毕,就清栈,恢复现场。  
   
  现在来考虑一下递归调用的情况  
  f(int   n)  
  {  
    if(n==0)return   1;  
    else   return   n*f(n-1);  
  }  
   
  但调用这个函数的时候,按照我的思路走一边,看看有什么收获?Top

3 楼topikachu(皮皮)回复于 2002-06-13 13:39:39 得分 15

一.为了支持函数调用,编译器必需要建栈.没有栈的编译器无法支持函数调用.  
  二.一般的c++编译器对于函数调用压栈有框架可以套用(inline不算)  
  如下形式  
   
  函数参数  
  返回地址  
  局部变量  
   
  当进行函数递归时,编译器在栈下方(逻辑上的,实际上可以是任一个方向,由编译器作者决定),继续依次压栈.  
  如果一个函数调用结束,就把栈指针往上移动,下部的数据就无效了.只要不超出栈的范围,调用就可以一直进行下去.  
   
  见   "c++编程思想"   p180   函数调用框架Top

4 楼ckacka(/*小红帽*/ckacka();)回复于 2002-06-13 14:27:39 得分 0

就是一个栈了,没有栈,很多东西在我们编程的时候都很难实现!Top

5 楼J_John()回复于 2002-06-13 14:34:52 得分 5

该讲的上面的几位大虾都讲过了,我就提一下  
  学习汇编最能解决你的问题.因为在汇编里面使用call调用其它地址的代码时,要么在call指令前将调用者的各个寄存器压入栈保存,要么在被调用者的首几行代码对被调用者将用的寄存器数据作压栈处理,否则,寄存器的数据将被覆盖.所以函数调用一般是用栈实现.Top

6 楼doer_ljy(可战)回复于 2002-06-13 14:40:56 得分 5

大侠们说得很透彻,我的理解就是不断的保存现场。  
  先保存现场推栈,在进行下一次程序。  
  在保存下一次程序的现场,……  
  直到有一次程序没有进栈,而是返回了。  
  在一层一层的恢复现场向下执行!  
  Top

7 楼daehappy(追求120%结贴)回复于 2002-06-13 23:00:15 得分 0

up!关注!Top

8 楼steedhorse(晨星)回复于 2002-06-13 23:27:09 得分 20

系统从来不知道当前在做的事情是不是“递归”,所以“递归”完全是一个算法的概念,而不是程序执行的概念,是不是递归,只能从你写的代码中看出来。系统知识允许你的函数调用它自身而已,只不过这一允许就等于允许了递归。  
  系统对于所有的函数调用,都是使用栈来管理。对于系统来讲,一个函数调用的函数是它自身还是别的函数是没有任何区别的,但从算法上考虑,一个函数调用它自身跟调用别的函数显然就有区别了。  
  因为调用自身意味着“里层的自身”还是要调用自身(就像用一面镜子照另一面镜子的情况),所以很可能导致栈的迅速膨胀。而调用另外一个函数,则是执行完了就了事(间接递归除外),栈也就缩短。有些问题天生就是递归的,所以使用递归来解非常方便。  
  总之,递归和栈没有什么单独的必然联系,函数调用的栈的机制是针对所有函数的,而不是单独针对递归的。  
  你胡涂就胡涂在以为系统对递归调用进行了特殊处理,根本没有。  
  不给分算了,递归不是自身调用自身还能是是什么?Top

9 楼maoliao(毛料)回复于 2002-06-14 01:01:49 得分 15

给你一个建议,用vc++调试时观察调用堆栈窗口及内存窗口就明白了  
   
  首先将函数改写为以下(借用richard_hu(华仔)的例子^$^,便于观察)  
  int   f1(int   n)  
  {  
  int   tmp=0;  
  int   tmp1=1;  
  if(n==0)  
  return   1;  
  else  
  {  
  tmp1=f1(n-1);  
  tmp=n*tmp1;  
  }  
  return   tmp;  
  }Top

10 楼ajoo(聪明的一猪)回复于 2002-06-14 01:31:58 得分 10

the   machine,   cpu,won't   care   you   are   doing   recursion   or   not.  
  But   compiler   does.  
   
  if   you   are   doing   tail   recursion   like  
  int   fact(int   i,   int   sofar){return   i==0?   1:   fact(i-1,   sofar*i);}  
  smart   compilers   will   use   "jmp"   instead   of   "call"   in   the   assembly.   That   means,   no   pushing   stack.  
  Top

11 楼Linux2001(闭关开发中)回复于 2002-06-14 07:56:19 得分 0

原理非常简单,就是函数执行过程中,发现了函数调用(递规部分)就把函数调用的下一条指令地址压栈,然后跳转到递规部分执行,执行完成以后把指令地址出栈,然后执行!就是如此而已Top

12 楼dyugao(晕头转向)回复于 2002-06-14 08:25:55 得分 0

好贴,标记。Top

13 楼sjie_ji(青藤)回复于 2002-06-14 09:16:35 得分 0

to   steedhorse(晨星)   :  
        领略君之谦虚治学分度,有点自愧不如。说实在的,在看到这个帖子的时候我第一反映就是不回答诸如此类拿着分就像面包一样在喊“我有面包,来食吧”。可是后来一想,也没有什么,可能是楼主一时没有太在意这些了。  
        一个产业的发展与成熟,总的有好多布道者。又何必斤斤计较那些这些小的细节呢?    
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1199552次
    • 积分:10960
    • 等级:
    • 排名:第1503名
    • 原创:47篇
    • 转载:378篇
    • 译文:4篇
    • 评论:212条