c语言 递归的执行过程探究

引用《c primer plus》第五版 9.3.1 递归的使用

 /* recur.c -- recursion illustration */
#include <stdio.h>
void up_and_down(int); int main(void)
{
up_and_down();
return ;
} void up_and_down(int n)
{
printf("Level %d: n location %p\n", n, &n); /* 1 */
if (n < )
up_and_down(n+);             /* 递归处 */  
printf("LEVEL %d: n location %p\n", n, &n); /* 2 */ }
过程:  main()调用了up_and_down(1),
然后第一层的up_and_down(此时n为1),
执行到了我注释的那个地方/*递归处*/即第15行
在递归处调用了up_and_down(调用时将n+1(也就是1+1)赋给了第二层的参量n) 由于调用后第一层要等待第二层的返回,所以第一层执行还没有完成,所以还轮不到第一层的/* 2 */ 处的打印,
第二层的up_and_down又执行到了/*递归处*/,又调用了函数,以此类推。
最后执行到了最深层时,n不再满足小于4的条件,所以不再递归。
就执行了/* 2 */ 处的打印,然后函数结束了,就return返回值【此处return void;】并退出当前层的函数
次深层检测到 被自己调用的函数的返回值 后继续执行/* 2 */ 处的打印,结束后再return void; 依次类推。
 

输出结果为:

LEVEL 1: n location 0x0012ff48
LEVEL 2: n location 0x0012ff3c
LEVEL 3: n location 0x0012ff30
LEVEL 4: n location 0x0012ff24
LEVEL 4: n location 0x0012ff24
LEVEL 3: n location 0x0012ff30
LEVEL 2: n location 0x0012ff3c
LEVEL 1: n location 0x0012ff48

总结:由于c语言的顺序结构,所以调用函数后要等待被调用的函数执行完成(即有返回值后)才能执行下一步,而递归恰恰是一层一层地调用自己,所以得等到最深层执行完成后,才返回值告诉次深层函数可以继续执行。次深层执行后才能返回告诉次次深层继续执行。
【在函数没有执行完成前,不return。 导致了每一个函数都得等待被调用函数的返回才能继续,不断调用就得不断等待被调用的函数,因此必须等最深层函数开始返回后才有了一步步的函数的后续执行和返回】

重点:调用时的LEVEL1地址和返回时的LEVEL1(LEVEL数字)是相同的
每一级递归都使用自己的私有变量(子函数中变量的作用域和储存时期部分的知识) 关于利用递归函数赋值的部分,引用《c primer plus》第五版 9.3.3尾递归
 // factor.c -- uses loops and recursion to calculate factorials
#include <stdio.h>
long fact(int n);
long rfact(int n);
int main(void)
{
int num; printf("This program calculates factorials.\n");
printf("Enter a value in the range 0-12 (q to quit):\n");
while (scanf("%d", &num) == )
{
if (num < )
printf("No negative numbers, please.\n");
else if (num > )
printf("Keep input under 13.\n");
else
{
printf("loop: %d factorial = %ld\n",
num, fact(num));
printf("recursion: %d factorial = %ld\n",
num, rfact(num));
}
printf("Enter a value in the range 0-12 (q to quit):\n");
}
printf("Bye.\n"); return ;
} long fact(int n) // loop-based function
{
long ans; for (ans = ; n > ; n--)
ans *= n; return ans;
} long rfact(int n) // recursive version
{
long ans; if (n > )
ans= n * rfact(n-);
else
ans = ; return ans;
}

首先,此处的赋值是    将 函数返回值 赋给一个变量

所以递归赋值这种也是一样的:
一步步等待,直到最深层函数执行完成并返回后
次深层才能利用返回值执行赋值操作,然后再执行完成并返回
次次深层才能利用返回值执行赋值操作......
依次类推 疑问递归函数里 x=3+addall(n);
那么x的值在递归过程中如何变化? =========End

【递归】执行过程探究(c)的更多相关文章

  1. Android UI测量、布局、绘制过程探究

    在上一篇博客<Android中Activity启动过程探究>中,已经从ActivityThread.main()开始,一路摸索到ViewRootImpl.performTraversals ...

  2. 多文件目录下makefile文件递归执行编译所有c文件

    首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的. 意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文 ...

  3. 【转】多文件目录下makefile文件递归执行编译所有c文件

    首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的. 意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文 ...

  4. koa执行过程原理分析

    本文原创,转载请注明出处https://i.cnblogs.com/EditPosts.aspx?postid=5710639 我们大家都知道,当koa接到请求经过中间件时,当执行到 yield ne ...

  5. webpack执行过程

    webpack-cli 执行过程 1.webpack.config.js,shell options参数解析 2.new webpack(options) 3.run() 编译的入口方法 4.comp ...

  6. TButton.Repaint的执行过程

    测试,在按钮事件里写上 Button1.Repaint;(包括TWinControl.Invalidate;和procedure TWinControl.Update;两个函数,会被TButton所继 ...

  7. python递归函数的执行过程

    举例: def nove(n,a,b,c): if n == 1: print(a,'------------>',c) else: nove(n-1,a,c,b) nove(1,a,b,c) ...

  8. mysql数据库查询过程探究和优化建议

    查询过程探究 我们先看一下向mysql发送一个查询请求时,mysql做了什么? 如上图所示,查询执行的过程大概可分为6个步骤: 客户端向MySQL服务器发送一条查询请求 服务器首先检查查询缓存,如果命 ...

  9. 【JS】js引擎执行过程

    概述 js引擎执行过程主要分为三个阶段,分别是语法分析,预编译和执行阶段,上篇文章我们介绍了语法分析和预编译阶段,那么我们先做个简单概括,如下: 语法分析: 分别对加载完成的代码块进行语法检验,语法正 ...

随机推荐

  1. Spring @CrossOrigin 通配符 解决跨域问题

    @CrossOrigin 通配符 解决跨域问题 痛点: 对很多api接口需要 开放H5 Ajax跨域请求支持 由于环境多套域名不同,而CrossOrigin 原生只支持* 或者具体域名的跨域支持 所以 ...

  2. react 练习参考

    项目地址:https://gitee.com/dhclly/icedog.react React 练习项目 相关资源链接 React官方 https://reactjs.org React 中国 ht ...

  3. centos6 升级Git版本

    操作步骤如下: yum remove -y git #卸载旧版本Git yum install -y tk zlib-devel openssl-devel perl cpio expat-devel ...

  4. ELK学习笔记之Elasticsearch和Kibana数据导出实战

    0x00 问题引出 以下两个导出问题来自Elastic中文社区. 问题1.kibana怎么导出查询数据?问题2:elasticsearch数据导出就像数据库数据导出一样,elasticsearch可以 ...

  5. Visual Studio2017使用EF添加Mysql

    为了能够在Visual Studio 中集成Mysql, 首先需要安装MySql的连接工具 与 MySql的VisualStudio插件. MySQL Connector Net 6.8.8 (目前最 ...

  6. 一文让你读懂Synchronized底层实现,秒杀面试官

    本文为死磕Synchronized底层实现第三篇文章,内容为轻量级锁实现. 轻量级锁并不复杂,其中很多内容在偏向锁一文中已提及过,与本文内容会有部分重叠. 另外轻量级锁的背景和基本流程在概论中已有讲解 ...

  7. EntityUtils.toString(entity)处理字符集问题解决

    爬取51Job和猎聘网的信息,想处理字符集问题(51job为gbk,猎聘为utf-8), 找到两个网站字符集信息都在同一标签下 就想先把网页保存成String,解析一遍获取字符集,然后将网页转换成对应 ...

  8. Python【day 12】生成器和推导式

    一.生成器和生成器函数1.生成器和生成器函数的概念 1.生成器的本质是迭代器 2.函数中包含yield,就是生成器函数 2.生成器函数的写法 def func(): a =10 yield 20 ge ...

  9. React用脚手架实际开发项目!

    安装脚手架: npm i create-react-app -g 创建项目命令: create-react-app 项目名字 启动命令:yarn start 如果不用脚手架,需要创建一下页面: 再安装 ...

  10. CTF必备技能丨Linux Pwn入门教程——ROP技术(下)

    Linux Pwn入门教程系列分享如约而至,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...