探索 C 语言的递归函数
《C Primer Plus》函数章节:递归函数。结合 Visual Studio 调试理解 C 语言的递归函数,下面是书上一模一样的代码,贴在这里:
#include<stdio.h>
void up_and_down(int);
int main(void)
{
up_and_down(1);
return 0;
}
void up_and_down(int n)
{
printf("Level %d: n location %p\n", n, &n);
if (n < 4)
{
up_and_down(n + 1);
}
printf("LEVEL %d: n location %p\n", n, &n);
}
通过指针运算符可以查看到这个变量的内存地址信息。在格式化打印语句里取值就是%p,按照十六进制输出,而%d是按十进制输出。

可以看到变量 n 的地址在前 4 次都发生变化,这是因为传递给函数的变量是属于函数的,它是一个局部变量,因此地址不一样。后四次 n 变量的地址与前面的地址信息呈倒转的现象,是因为递归函数在往回执行导致的结果。
if n < 4,所以最多只能执行四次up_and_down()函数。请注意,这四次执行完成之后,后面还有一个打印语句,它还没有被执行,也就是说,递归函数在哪里,那么后面的代码就被“截断”暂时不执行:

可以发现,行 18 累计了 4 次,然后依次从高到低由往回执行,也就是图1显示的效果。下图是递归函数执行的流程图:

第 1~4 级函数执行自己的时候,n 在逐步自增 1,直到第 4 级递归函数不符合 if 条件,就开始从第 4 级函数依次返回执行。根据图1可知,每一级函数接收的变量 n 都是独立的内存地址。所以,依次返回执行每一级的函数的变量 n 看似就是在自减。
递归有时候难以捉摸,有时候却很方便实用。结束递归是使用递归的难点,因为递归代码中没有终止递归的条件,就会无限递归。可以使用循环的地方通常可以使用递归,有时候用循环解决问题比较好,但有时候用递归更好。递归比较消耗计算机内存,每递归一次,里面的变量就要重新创建一次,图1已经证实了这一点。
探索 C 语言的递归函数的更多相关文章
- [转]深度探索C语言函数可变长参数
转自:http://www.cnblogs.com/chinazhangjie/archive/2012/08/18/2645475.html 一.基础部分 1.1 什么是可变长参数 可变长参数:顾名 ...
- 探索Java语言与JVM中的Lambda表达式
Lambda表达式是自Java SE 5引入泛型以来最重大的Java语言新特性,本文是2012年度最后一期Java Magazine中的一篇文章,它介绍了Lamdba的设计初衷,应用场景与基本语法.( ...
- 【C语言】递归函数DigitSum(n)
//写一个递归函数DigitSum(n),输入一个非负整数,返回组成它的数字之和, //比如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19 #include <std ...
- 深度探索Go语言:包装方法
问题1:什么是包装方法? 下面咱们来验证下包装方法的存在: 首先,定义一个Point类型,表示一维坐标系内的一个点,并且按照Go语言的风格为其实现了一个Get方法和一个Set方法. package g ...
- C语言:递归函数n!
#include <stdio.h> long recursion(int n); void main(){ int n; long result; printf("input ...
- 【C语言探索之旅】 开宗明义及第一课:什么是编程?
内容简介 1.课程大纲 2.第一部分第一课:什么是编程? 3.第一部分第二课预告:工欲善其事,必先利其器 课程大纲 不知道为什么,一直对C语言有一种很深厚的“情怀”(类似老罗对锤子手机的那种),说 ...
- Go 语言递归函数
递归,就是在运行的过程中调用自己. 语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recursion() } ...
- Go语言【第十三篇】:Go语言递归函数
Go语言递归函数 递归,就是在运行的过程中调用自己,语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recurs ...
- GO语言学习(二十)Go 语言递归函数
Go 语言递归函数 递归,就是在运行的过程中调用自己. 语法格式如下: func recursion() { recursion() /* 函数调用自身 */ } func main() { recu ...
- PHP内核探索之变量(6)- 后续内核探索系列大纲备忘
年前因为工作比较饱和,现在又忙着换工作的事情,基本停止了对博文的更新.后续的博文,还是慢慢补上吧. 为了不至于过于发散,先搞个未成形的大纲,如下: PHP内核探索之变量 不平凡的字符串 PHP内核探 ...
随机推荐
- 【JVM调优】Day02:CMS的三色标记算法、分区的G1回收器、短时停顿的ZGC回收器
一.CMS及其三色标记算法 1.核心 标记整个图谱的过程分为多步 多个线程相互工作,才能标记完 标记的算法,JVM虚拟机.go语言使用的都是三色标记算法 2.含义 从那个地方开始,用三种颜色替代 一开 ...
- jjava基础语法
java基础语法1 注释 注意: SDK要选择JDK1.8,且下面的语言要选择8,配置完这个环境后,JAVA才能正常运行. 单行注释 //+text 快捷键:ctrl+/ 多行注释 /*+text+ ...
- 基础css样式
目录 css层叠样式表 css选择器 伪类选择器 选择器生效优先级 css字体颜色背景 设置宽高 边框 display属性 div盒子模型 float漂浮 溢出overflow 定位(position ...
- 协程- gevent模块
协程 1.什么是协助:在单线程下实现并发效果 2.协程的原理: 通过代码监听IO操作一旦遇到 IO 操作就立刻切换下一个程序 让cpu一直在工作 这样就可以一直占用CPU的效率 提高程序执行效率 切换 ...
- .NET周报【12月第1期 2022-12-08】
国内文章 CAP 7.0 版本发布通告 - 支持延迟消息,性能炸了? https://www.cnblogs.com/savorboard/p/cap-7-0.html) 今天,我们很高兴宣布 CAP ...
- Karmada多云多集群生产实践专场圆满落幕
摘要:CNCF Karmada社区Cloud Native Days China 2022南京站成功举办. 本文分享自华为云社区<Karmada多云多集群生产实践专场圆满落幕|Cloud Nat ...
- PHP 实现大文件视频推流
/** * 视频推流 * 返回视频流 */ function bofang(){ set_time_limit(0); ini_set('max_execution_time', 0);//秒为单位, ...
- [常用工具] PyAutoGUI使用教程
PyAutoGUI使用教程 目录 PyAutoGUI使用教程 1 基础知识 2 一般函数 3 故障保险 4 鼠标函数 4.1 鼠标移动 4.2 鼠标拖动 4.3 鼠标单击 4.4 鼠标滚动 4.5 鼠 ...
- 那些年我们用过的组件-结构化日志组件 Serilog
什么是结构化日志 我们记录日志惯常使用 log4j2.NLog 等日志组件,这些组件提供了输出到多种终端的能力,但是大部分时候我们选择将日志输出到操作系统的文件系统中,为什么呢?至少有一部分原因是记录 ...
- 小样本利器5. 半监督集各家所长:MixMatch,MixText,UDA,FixMatch
在前面的几个章节中,我们介绍了几种基于不同半监督假设的模型优化方案,包括Mean Teacher等一致性正则约束,FGM等对抗训练,min Entropy等最小熵原则,以及Mixup等增强方案.虽然出 ...