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

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

TreeMap的实现原理

TreeMap的结构是红黑树又称红-黑二叉树,它首先是一颗二叉树,它具体二叉树所有的特性。同时红黑树更是一颗自平衡的排序二叉树。关于红-黑二叉树,可以参考:点击打开链接 在这里,我们主要简单...
  • ycs694153581
  • ycs694153581
  • 2015年03月31日 15:49
  • 1303

Aop实现原理详解

一、什么是 AOP AOP(Aspect-OrientedProgramming,面向切面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。...
  • a123demi
  • a123demi
  • 2016年11月15日 16:49
  • 3653

HashMap实现原理分析

HashMap其实也是一个线性的数组实现的,所以可以理解为其存储数据的容器就是一个线性数组。这可能让我们很不解,一个线性的数组怎么实现按键值对来存取数据呢?这里HashMap有做一些处理。   首先...
  • vking_wang
  • vking_wang
  • 2013年11月05日 15:23
  • 291732

tomcat原理解析(一):一个简单的实现

一,概述     前段时间去面试,被人问到了tomcat实现原理。由于平时没怎么关注容器的实现细节,这个问题基本没回答上来。所以最近花了很多时间一直在网上找资料和看tomcat的源码来研究里面处理一个...
  • qiangcai
  • qiangcai
  • 2017年03月07日 09:54
  • 3130

hashmap与Hashtable实现原理浅析

原文地址:http://www.cnblogs.com/lzrabbit/p/3721067.html#h1 HashMap和Hashtable的区别两者最主要的区别在于Hashtable是线程安全,...
  • Double2hao
  • Double2hao
  • 2016年11月30日 18:21
  • 3565

验证码的原理、作用及实现

验证码能有效阻止恶意登录与注册, 这里主要是验证码的相关原理及操作实现。所用知识为 javaweb 的 jsp servlet xml 及 java 基础知识。...
  • niaonao
  • niaonao
  • 2016年04月10日 14:13
  • 15034

集合各实现类的底层实现原理

ArrayList实现原理要点概括参考文献:http://zhangshixi.iteye.com/blog/674856l ArrayList是List接口的可变数组非同步实现,并允许包括null在...
  • qq_25868207
  • qq_25868207
  • 2017年02月16日 16:11
  • 9040

Promise实现原理

新到公司接手新项目,发现网络层使用的Promise原理搭建的基层,感觉挺有意思,做点记录吧。Promise 类似于一个事务管理器,它的作用就是将各种内嵌回调的事务用流水形式表达。利用 Promise ...
  • a1484
  • a1484
  • 2016年07月25日 15:11
  • 2320

C/C++知识要点2——STL中Vector、Map、Set容器的实现原理

1、Vector是顺序容器,是一个动态数组,支持随机存取、插入、删除、查找等操作,在内存中是一块连续的空间。在原有空间不够情况下自动分配空间,增加为原来的两倍。vector随机存取效率高,但是在vec...
  • TommyZht
  • TommyZht
  • 2015年08月06日 10:40
  • 3621

ping实现原理

ping命令是用来查看网络上另一个主机系统的网络连接是否正常的一个工具。ping命令的工作原理是:向网络上的另一个主机系统发送ICMP报文,如果指定系统得到了报文,它将把报文一模一样地传回给发送者,这...
  • wuheshi
  • wuheshi
  • 2016年03月16日 13:38
  • 3645
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:递归函数内部的原理????不要跟我讲自己调用自己这样的话,我一分也不给你的zz
举报原因:
原因补充:

(最多只允许输入30个字)