user-0 提问: 递归在底层是怎么实现的？

回复:
user: user-0
content: 引用 10 楼 zilaishuichina 的回复:尾递归可以优化成循环   递归调用 就是 函数调用， 递归调用的函数自己调用自己。 而函数调用的原理就是保存现场，调用另一个函数（递归时这个另一个函数就是自己），恢复现场继续执行 保存现场包括保存函数调用的下一条指令的地址eip，栈帧指针ebp，esp，子函数参数列表  也正因为是自己调用自己， 所以需要一个结束自己调用自己的契机，叫做递归出口。  也正因为保存现场需要保存一系列的参数压栈， 如果没有递归出口，就是死循环在不停的压栈，而栈空间是由限的， 所以如果没有递归出口，就会造成栈溢出详细，

user: user-0
content: 引用 3 楼 zhao4zhong1 的回复:“给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出这个汉诺塔问题，传参数，真的不太懂。

user: user-0
content: 引用 2 楼 xiaohuh421 的回复:递归的原理, 你可以想像成不停的函数调用.  比如fun1  ---  funN都是实现Add  fun1() {       fun2() {     fun3()     {       ........     } }   }  递归的核心思想就是保存现场,  也就是需要把传入下一层函数的所有参数保存起来, 实现函数参数栈.这样理解好，很形象

user: user-1
content: 尾递归可以优化成循环   递归调用 就是 函数调用， 递归调用的函数自己调用自己。 而函数调用的原理就是保存现场，调用另一个函数（递归时这个另一个函数就是自己），恢复现场继续执行 保存现场包括保存函数调用的下一条指令的地址eip，栈帧指针ebp，esp，子函数参数列表  也正因为是自己调用自己， 所以需要一个结束自己调用自己的契机，叫做递归出口。  也正因为保存现场需要保存一系列的参数压栈， 如果没有递归出口，就是死循环在不停的压栈，而栈空间是由限的， 所以如果没有递归出口，就会造成栈溢出

user: user-2
content: 引用 1 楼 kaituozhe163 的回复:老师说，能用递归实现的算法，都能用循环实现，哪位大神能帮我用循环实现一下，汉诺塔问题的算法： 汉诺塔递归： void  haNoTower(int n,char start,char temp,char end) {     int count = 0;     if(n == 1)     {         printf("第%d个盘子从%c->%c\n",n,start,end);     }     else     {         haNoTower(n - 1,start,end,temp);         printf("第%d个盘子从%c->%c\n",n ,start,end);         count++;         haNoTower(n - 1,temp,start,end);//问什么要写n － 1 呢？     }  最笨的办法： 先写递归版本， 用栈(数据结构）来模拟函数调用。

user: user-3
content: 函数调用所做的事情 调用前： 1）函数参数处理-------------//参数存入寄存器，或者压栈 2）函数返回地址处理--------//把地址保存到栈内，以便返回时可以找到返回位置。 调用中： 3）执行函数体 调用后： 4）堆栈平衡和函数返回值处理----------//合理利用堆栈，寄存器，不至于浪费空间。 大约做了这么多事情  1）2）4） 这几步，通常就是某些书中说的簿记管理， 这是每个函数调用都在做的， 可能还包括更加常用的出栈入栈 递归只是利用了这种簿记管理，而不是递归独有的

user: user-3
content: 递归函数，自己直接间接调用自己

user: user-3
content: 递归，和普通函数调用，没有太多不同 不同的是，函数自己调用自己 底层实现，没区别，或者基本没区别  一般CPU 没区别 51 再入函数实现递归，普通函数不行。

user: user-4
content: 递归是自顶向下的思想, 象汉诺塔,看起来就简洁, 用循环就麻烦多了, 还是多理解一下递归吧

user: user-5
content: 引用 1 楼 kaituozhe163 的回复:老师说，能用递归实现的算法，都能用循环实现，哪位大神能帮我用循环实现一下，汉诺塔问题的算法： 汉诺塔递归： void  haNoTower(int n,char start,char temp,char end) {     int count = 0;     if(n == 1)     {         printf("第%d个盘子从%c->%c\n",n,start,end);     }     else     {         haNoTower(n - 1,start,end,temp);         printf("第%d个盘子从%c->%c\n",n ,start,end);         count++;         haNoTower(n - 1,temp,start,end);//问什么要写n － 1 呢？     }  要想将n个盘子从A挪到C，首先得将前n-1个盘子挪到B，接着将最底下的盘子挪到C，然后将B中的盘子挪到C  如程序： haNoTower(n - 1,start,end,temp);   //将前n-1个盘子从start借助end挪到temp printf("第%d个盘子从%c->%c\n",n ,start,end);   //将最后一个盘子从start挪到end  haNoTower(n - 1,temp,start,end);    //将前n-1个盘子从temp借助start挪到end

user: user-6
content: “给定一个小点的输入，完整单步跟踪(同时按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史)一遍。”是理解递归函数工作原理的不二法门！ 递归函数关注以下几个因素 ·退出条件 ·参数有哪些 ·返回值是什么 ·局部变量有哪些 ·全局变量有哪些 ·何时输出 ·会不会导致堆栈溢出

user: user-7
content: 递归的原理, 你可以想像成不停的函数调用.  比如fun1  ---  funN都是实现Add  fun1() {       fun2() {     fun3()     {       ........     } }   }  递归的核心思想就是保存现场,  也就是需要把传入下一层函数的所有参数保存起来, 实现函数参数栈.

user: user-3
content: 引用 8 楼 TheOne_jie 的回复:有了栈就有了递归

user: user-8
content: 有了栈就有了递归

user: user-3
content: 簿记管理，没有多少编译器，CPU专门去做， 而是函数调用，自然就有这个管理工作在内

user: user-3
content: 底层，什么也不做，所谓簿记管理，其实只是编译器，硬件底层堆栈实现，等调用函数的正常功能 只有特殊CPU比如51 需要专门类型的再入函数，实现递归  普通CPU 递归函数调用，和普通函数调用，实现方法一致。

user: user-0
content: 老师说，能用递归实现的算法，都能用循环实现，哪位大神能帮我用循环实现一下，汉诺塔问题的算法： 汉诺塔递归： void  haNoTower(int n,char start,char temp,char end) {     int count = 0;     if(n == 1)     {         printf("第%d个盘子从%c->%c\n",n,start,end);     }     else     {         haNoTower(n - 1,start,end,temp);         printf("第%d个盘子从%c->%c\n",n ,start,end);         count++;         haNoTower(n - 1,temp,start,end);//问什么要写n － 1 呢？     }