嵌入式初学-C语言-十七
#接嵌入式初学-C语言-十六#
函数的递归调用
含义:
在一个函数中直接或者间接调用了函数本身,称之为函数的递归调用
// 直接调用a()->a();
// 间接调用a()->b()->a();a()->b()->..->a();
递归调用的本质:
本是是一种循环结构,它不同于之前所学的while,do-while,for这样的循环结构,这些循环结构是借助循环变量,而递归是利用了函数自身实现循环结构,如果不加以控制,很容易产生死循环
递归调用的注意事项:
- 递归调用必须要有出口,一定要终止递归,否则会产生死循环
- 对终止条件的判断一定要放在函数递归之前。
- 进行函数的递归调用
- 函数递归调用的同时一定要将函数调用向出口逼近
案例1:
/**
* 需求:递归案例-有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人大2岁。最后问第1个人,他说是10岁。请问第5个人多大。
*/
#include <stdio.h>
/* 求年龄的递归函数 */int age(int n)
{// 存放函数的返回值,也就是年龄int c;if(n == 1){c = 10;// 第一个人的年龄是10岁}else if(n > 1){c = age(n-1)+2; // 当前这个人的年龄 = 上一个人的年龄+2}return c;
}int main()
{printf("%d\n",age(5));return 0;
}
案例2:
/**
* 需求:递归案例-求阶乘(n!)
*/
#include <stdio.h>/* 编写一个函数,用来求阶乘 */
long fac(int n)
{// 因为int型表示的数据范围小,所以乘法操作我们使用long来接收计算结果long f;if(n < 0){printf("n的范围不能是0以下的数!\n");}else if(n == 0 || n==1) // 此时不满足阶乘条件{f = 1;}else{f = fac(n-1)*n;}return f;
}int main()
{int n;printf("请输入一个整数:\n");scanf("%d",&n);printf("%d!=%ld\n",n,fac(n));return 0;
}
数组作为函数参数
注意:
- 当用数组做函数的实际参数时,则形参应该也要用数组/指针变量来接收,但请注意,此次并不代表传递了数组中所有元素数据,而是传递了第一个元素的内存地址(数组首地址),形参接收这个地址后,形参和实参就代表了同一块内存空间,则形参的数据修改会改变实参的,这种数据传递方式我们可以称之为引用传递
- 如果用数组做函数的形式参数,那么我们提供另一个形参表是数组的元素个数,原因是数组形参代表的仅仅是实际数组的首地址,也就是说形参只获取到了实际数组元素的开始,并未获取到元素的结束,所以提供另一个形参,表示数组的元素个数,可以防止在被调函数对实际数组元素访问的越界
- 但有一个例外如果是以字符数组做形参,且实际数组中存放的是字符串数据(形参是字符数组,实参是字符串)则不用表示数组元素个数的形参,原因是字符串本身会自带结束符\0
案例-数组元素做函数实参:
/**
* 需求:数组为参数案例-有两个数组a和b,各有10个元素,将它们对应元素逐个地相比(即a[0]与b[0]比,a[1]
与b[1]比……)。如果a数组中的元素大于b数组中的相应元素的数目多于b数组中元素大于a数组中相应元素的数目(例
如,a[i]>b]i]6次,b[i]>a[i] 3次,其中i每次为不同的值),则认为a数组大于b数组,并分别统计出两个数组相应元
素大于、等于、小于的个数。
*
*/
#include <stdio.h>/* 定义一个函数,实现两个数的比较 */
int large(int x,int y)
{int flag;// 用来存放比较结果if(x > y) flag = 1;else if(x < y) flag = -1;else flag = 0;return flag;
}int main()
{// 比较用的两个数组,循环变量,最大,最小,相等int a[10],b[10],i,max=0,min=0,k=0;printf("请给数组a添加十个整型数据:\n");for(i = 0;i < sizeof(a)/sizeof(int);i++){scanf("%d",&a[i]);}printf("\n");printf("请给数组b添加十个整型数据:\n");for(i = 0;i < sizeof(b)/sizeof(int);i++)scanf("%d",&b[i]);printf("\n");// 遍历for(i = 0;i < sizeof(a)/sizeof(int);i++){if(large(a[i],b[i])==1){max++;}else if(large(a[i],b[i])==0){k++;}else{min++;}}printf("max=%d,min=%d,k=%d\n",max,min,k);return 0;
}
案例2:
/**
* 需求:数组函数的参数案例-编写一个函数,用来分别求数组score_1(有5个元素)和数组score_2(有10个元素)
各元素的平均值 。
*/
#include <stdio.h>
/* 定义一个函数,用来求平均分 */
float avg(float scores[],int len)
{int i;// 循环变量float aver,sum = scores[0];// 保存平均分和总成绩// 遍历集合for(i = 1;i < len;i++){sum += scores[i];}aver = sum / len;return aver;
}int main()
{//准备俩测试数组float score_1[5] = {66,34,46,37,97};float score_2[10] = {77,88,66,55,65,76,87,98,75,34};printf("这个班的平均分是:%6.2f\n",avg(score_1,sizeof(score_1)/sizeof(float)));printf("这个班的平均分是:%6.2f\n",avg(score_2,sizeof(score_2)/sizeof(float)));return 0;
}
变量的作用域
引入问题
我们在函数设计过程中,经常要考虑对参数的设计,换句话说,我们需要考虑函数需要几个参数,需 要什么类型的参数,但我并没有考虑函数是否需要提供参数,如果说函数可以访问到已定义的数据, 则就不需要提供函数形参,那么我么到底要不要提供函数参数,取决于什么?答案就是变量的作用域 (如果函数在变量的作用域范围内,则函数可以直接访问数据)
变量的作用域
概念:变量的作用范围,也就是说变量在什么范围是有效的
变量的分类
根据变量的作用域不同,变量可分为全局变量和局部变量
局部变量
| 序号 | 局部变量 | 作用域 |
| 1 | 形式参数(形参) | 函数作用域 |
| 2 | 函数内定义的变量 | 函数作用域 |
| 3 | 复合语句中定义的变量 | 块作用域 |
| 4 | for循环表达式1定义的变量 | 块作用域 |
全局变量
| 序号 | 全局变量 | 作用域 |
| 1 | 定义在函数之外的变量,也称为外部变量或全程变量 | 全局变量定义处到本源文件结束 |
建议在全局变量定义时初始化,如果不初始化,系统会将全局变量初始化为0
- 使用全局变量的优缺点
优点:
- 利用全局变量可以实现函数对外输出的多个结果数据
- 利用全局变量可以减少函数形参个数,从而降低内存消耗,以及因形参传递带来的时间消耗
缺点
- 全局变量在整个程序运行期间,始终占据内存空间,会引起资源消耗
- 过多的全局变量会引起程序的混乱,造成程序结果错误
- 降低程序通用性,特别是当我们进行函数移植时,不仅仅要移植函数,还要考虑全局变量
- 违反了”高内聚,低耦合”的程序设计原则
总结:我们发现弊大于利,建议尽量减少对全局变量的使用,函数之间要产生联系,仅通过实参,形参的方式产生联系
作用域举例:

案例:
int p=1,q=5; /*外部变量p,q*/
float f1(int a) /*定义函数f1*/
{ int b,c;
…
}
char c1,c2; /*外部变量c1,c2*/
char f2 (int x, int y) /*定义函数f2*/
{ int i,j;
…
}
void main ( ) /*主函数*/
{ int m,n;
…
}
注意:
如果全局变量和局部变量同名,程序执行的时候就近原则
int a = 10;
int main()
{
int i = 20;
printf("%d\n",a); // 20 就近原则
for(int i = 0;i < 5; i++)
{
printf("i=%d ",i); // 0 1 2 3 4 就近原则
}
}
相关文章:
嵌入式初学-C语言-十七
#接嵌入式初学-C语言-十六# 函数的递归调用 含义: 在一个函数中直接或者间接调用了函数本身,称之为函数的递归调用 // 直接调用a()->a(); // 间接调用a()->b()->a();a()->b()->..->a();递归调用的本质: 本是是一种循环…...
leetcode数论(2280. 表示一个折线图的最少线段数)-几何
前言 经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。 数论包含最大公约数(>2个数)、最大公约数性质、最小公倍数、区间范围质因素计数(最下间隔)、质因素分解、判断质数、平方根、立方根、互质、同余等等。 描述 给…...
如何利用 LNMP 搭建 WordPress 站点
作者 乐维社区(forum.lwops.cn) 许远 在这个信息爆炸的时代,拥有一个能够迅速传达信息、展示个性、并能够与世界互动的在线平台,已成为企业和个人的基本需求。WordPress,以其无与伦比的易用性和强大的扩展性࿰…...
“Mutation Observer:让DOM变化尽在掌握
Mutation Observer(变动观察者) 定义 Mutation Observer是一种JavaScript API,用于异步监测DOM树的变动,包括元素的添加、删除、属性变化等。当DOM发生变动时,它可以触发回调函数,允许你对变动作出响应。 …...
oracle(19c)用户管理
简介 本文介绍 Oracle 中的用户管理,包含以下内容: 概念介绍 系统用户 解锁 hr 用户 创建用户 用户相关案例 使用 Profile 管理用户口令 Oracle 的认证方式 重置管理员(sys)密码 1. 概念介绍 使用前可以自行安装oracle数据库 oracle19c安装&a…...
浅谈安科瑞智慧用电系统在电气火灾中的应用
摘要:为了对电气火灾事故进行预测和预警,同时为了对电气火灾事故的应急救援提供 支持,将智慧用电监控系统应用于电气火灾中。该系统利用物联网、移动互联网、云平台、大数据技术,实现对电气线路电流、漏电、温度、谐波等参数进行…...
【Material-UI】Button 组件中的尺寸设置(Sizes)详解
文章目录 一、基础尺寸选项1. 小尺寸(Small)2. 中等尺寸(Medium)3. 大尺寸(Large) 二、尺寸的应用场景三、高级用法和最佳实践1. 使用主题调整默认尺寸2. 确保一致性3. 考虑无障碍设计 四、总结 在用户界面…...
Java学习Day20
Vue学习 nodejs的安装与环境配置 1.直接去官网下载合适版本的nodejs( https://nodejs.org/zh-cn/download/prebuilt-installer) 2.解压下载的安装包,将文件路径配置到系统变量的path中,然后确认后退出。可以使用终端来查看安装的nodejs版本。使用winR…...
代理IP怎么弄,如何在电脑中设置IPXProxy代理IP?
随着互联网的不断普及,人们可以利用网络在不同的领域实现更多的可能性。在这个过程中,许多新型网络技术受到人们的关注,代理IP就是其中之一。使用代理IP可以隐藏真实的IP地址,帮助我们突破网络限制、保护隐私、进行网页抓取等一系…...
MacOS 查看端口命令
netstat 命令 查看所有监听的端口 netstat -nat | grep LISTEN 查看9000端口 netstat -nat | grep 9000 # 示例输出 tcp4 0 0 127.0.0.1.9000 *.* LISTEN lsof 命令 查看所有TCP监听的端口 lsof -n -P -i TCP -s TCP:LISTEN 参…...
【python】序列化与反序列化
序列化与反序列化 JSON、CSV和YAML都是常见的数据序列化和反序列化格式。它们都可以用于将数据从一种表示形式转换为另一种表示形式。 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它使用键值对的形式来表示数据ÿ…...
补充:关于GRU的详细运作原理以及特殊的优化思路
1. GRU的基本结构和运作原理 1.1 GRU的基本概念 Gated Recurrent Unit (GRU) 是一种简化版的循环神经网络 (RNN),它通过引入门控机制来解决长期依赖问题,同时减少参数数量以降低计算复杂度。 1.2 GRU的结构详解 GRU 包含两个门控机制:更新门 (update gate) 和重置门 (re…...
xxl-job 源码梳理(2)-服务端
目录 1. 控制面的接口2.手动触发任务2. 定时任务的实现 1. 控制面的接口 服务端包含xxl-job的管理端,页面上的接口后端一系列的controller接口 appName是一个核心概念,它是指执行器应用的名称,appName是执行器的唯一标识 页面上的接口&#…...
C++ GDl+ 多张图片合并生成GIF动画格式图片
使用ImageMagick多张图合成GIF。 1、工具下载安装 下载地址:ImageMagick – Download,windows下载版本如下: 下载后,安装,安装时选择为C/C安装动态库和头文件。 2、代码实现 附加包含目录:ImageMagick-7.…...
【C++】模拟实现list
🦄个人主页:修修修也 🎏所属专栏:实战项目集 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目及其功能 📌了解list官方标准 了解模拟实现list 📌了解更底层的list实现 二.list迭代器和vector迭代器的异同 📌迭…...
怎么使用git merge合并两个分支?
在Git中,git merge命令用于将两个或多个开发历史(通常指分支)合并到一起。以下是一个基本的步骤指南,说明如何使用git merge来合并两个分支。 ### 前提条件 - 确保你已经安装了Git,并且熟悉基本的Git命令,如…...
ios 5.5寸、ipad13英寸如何截屏
ios上架的时候,你可能会发现,上架需要ios 5.5寸,ipad需要13英寸的屏幕截屏。 但是尴尬了,我们手头上的手机,可能是最新的iphone 15,并没有远古时代iphone 8 plus的5.5寸,那么我们该如何截屏呢&…...
spdlog日志库--输出格式(fmt 库集成)
系列目录 spdlog日志库–基础介绍 spdlog日志库–源码解析 文章目录 1. 格式输出fmt格式输出2. format_spec 格式空间正数和负数的格式#号控制输出格式3. %s占位符 切换 {}占位符 (fmtlib(fmt::format)){}占位符 -> %s等占位符%s占位符 -> {}占位符4. 不使用占位符({}、%…...
Docker简介 MacM1安装Docker
文章目录 1 Docker简介2 Docker VS 虚拟机1 Docker优势2 Docker用途 3 MacM1 下载安装Docker1 配置环境变量 4 配置Docker2 设置Docker资源3 设置Docker镜像 参考 1 Docker简介 Docker主要解决了软件开发和运行配置的问题,但是由于其功能的强大,也被应用…...
【Linux】yum软件包管理器(使用、生态、yum源切换)
目录 1.yum-软件包管理器😸1.1yum使用方法1.2什么是yum?😸1.3yum的周边生态1.4yum源切换1.4.1 查看系统本身yum源1.4.2 软件源1.4.3yum源配置 1.yum-软件包管理器 以下操作需要联网的情况下进行 😸1.1yum使用方法 安装软件时由于需…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
