嵌入式初学-C语言-十七

#接嵌入式初学-C语言-十六#

函数的递归调用

含义:

在一个函数中直接或者间接调用了函数本身,称之为函数的递归调用

// 直接调用a()->a();
// 间接调用a()->b()->a();a()->b()->..->a();

递归调用的本质:

本是是一种循环结构,它不同于之前所学的while,do-while,for这样的循环结构,这些循环结构是借助循环变量,而递归是利用了函数自身实现循环结构,如果不加以控制,很容易产生死循环

递归调用的注意事项:

  1. 递归调用必须要有出口,一定要终止递归,否则会产生死循环
  2. 对终止条件的判断一定要放在函数递归之前。
  3. 进行函数的递归调用
  4. 函数递归调用的同时一定要将函数调用向出口逼近

案例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;
}

 

数组作为函数参数

注意:

  1. 当用数组做函数的实际参数时,则形参应该也要用数组/指针变量来接收,但请注意,此次并不代表传递了数组中所有元素数据,而是传递了第一个元素的内存地址(数组首地址),形参接收这个地址后,形参和实参就代表了同一块内存空间,则形参的数据修改会改变实参的,这种数据传递方式我们可以称之为引用传递
  2. 如果用数组做函数的形式参数,那么我们提供另一个形参表是数组的元素个数,原因是数组形参代表的仅仅是实际数组的首地址,也就是说形参只获取到了实际数组元素的开始,并未获取到元素的结束,所以提供另一个形参,表示数组的元素个数,可以防止在被调函数对实际数组元素访问的越界
  3. 但有一个例外如果是以字符数组做形参,且实际数组中存放的是字符串数据(形参是字符数组,实参是字符串)则不用表示数组元素个数的形参,原因是字符串本身会自带结束符\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

  1. 使用全局变量的优缺点

优点:

  1. 利用全局变量可以实现函数对外输出的多个结果数据
  2. 利用全局变量可以减少函数形参个数,从而降低内存消耗,以及因形参传递带来的时间消耗

        缺点

  1. 全局变量在整个程序运行期间,始终占据内存空间,会引起资源消耗
  2. 过多的全局变量会引起程序的混乱,造成程序结果错误
  3. 降低程序通用性,特别是当我们进行函数移植时,不仅仅要移植函数,还要考虑全局变量
  4. 违反了”高内聚,低耦合”的程序设计原则

总结:我们发现弊大于利,建议尽量减少对全局变量的使用,函数之间要产生联系,仅通过实参,形参的方式产生联系

作用域举例:

案例:

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 就近原则
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/394453.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【QT】Qt 音视频

Qt 音视频 Qt 音视频1. Qt 音频2. Qt 视频 Qt 音视频 在 Qt 中&#xff0c;音频主要是通过 QSound 类来实现。但是需要注意的是 QSound 类只支持播放 wav 格式的音频文件。也就是说如果想要添加音频效果&#xff0c;那么首先需要将非 wav 格式的音频文件转换为 wav 格式。 通…

JavaWeb之servlet关于Ajax实现前后端分离

一、什么是Ajax: AJAX Asynchronous JavaScript and XML&#xff08;异步的 JavaScript 和 XML&#xff09;。 AJAX 不是新的编程语言&#xff0c;而是一种使用现有标准的新方法。 AJAX 最大的优点是在不重新加载整个页面的情况下&#xff0c;可以与服务器交换数据并更新部…

Nuxt2:强制删除window.__NUXT__中的数据

一、问题描述 在以前的一篇文章《Nuxt3: 强制删除__NUXT_DATA__的一种方式》中曾介绍了在Nuxt3中如何删除存在于页面id为__NUXT_DATA__的script节点中的数据。 此次&#xff0c;Nuxt2与Nuxt3不同在于它的数据是存在于window.__NUXT__&#xff0c;那么该如何处理呢&#xff1f;…

2025深圳国际户外庭院营地用品博览会

2025深圳国际户外庭院营地用品博览会 2025 Shenzhen International Outdoor Courtyard Camping Supplies Expo 时间&#xff1a;2025年02月27-3月01日 地点&#xff1a;深圳会展中心&#xff08;福田馆&#xff09; 详询主办方陆先生 I38&#xff08;前三位&#xff09; …

如何用OceanBase与DataWorks,打造一站式的数据集成、开发和数据服务

导语&#xff1a;在OceanBase 2024年开发者大会的技术生态论坛上&#xff0c;阿里云DataWorks团队的高级技术专家罗海伟&#xff0c;详细阐述了一站式大数据开发治理平台DataWorks的能力&#xff0c;并对于如何基于OceanBase和Dataworks构建一站式数据集成、开发以及数据服务进…

Linux驱动开发—Linux内核定时器概念和使用详解,实现基于定时器的字符驱动

文章目录 内核定时器概念在Linux驱动模块中使用定时器软定时器&#xff08;Soft Timers&#xff09;jiffies 含义高精度定时器&#xff08;High Resolution Timers&#xff09; 实现倒计时字符设备驱动 内核定时器概念 在 Linux 内核中&#xff0c;定时器是用来管理和调度延迟…

8.7-主从数据库的配置+mysql的增删改查

一、mysql环境的配置 1.环境准备 &#xff08;1&#xff09;主数据库 #关闭防火墙 [rootmaster ~]# systemctl stop firewalld#关闭selinux [rootmaster ~]# setenforce 0#下载lrzsz工具 [rootmaster ~]# yum -y install lrzsz#安装rsync [rootmaster ~]# yum -y install rs…

低代码平台:效率利器还是质量妥协?

目录 低代码平台&#xff1a;效率利器还是质量妥协&#xff1f; 一、引言 二、低代码平台的定义和背景 1、什么是低代码平台&#xff1f; 2、低代码平台的兴起 三、低代码开发的机遇 1、提高开发效率 2、降低开发成本 3、赋能业务人员 四、低代码开发的挑战 1、质量…

pgbackrest备份方案(差异和增量备份的区别)

pgbackrest备份方案(差异和增量备份的区别) 一 备份 全量备份&#xff1a; 将数据库集群的全部内容复制到备份中。数据库集群的第一个备份始终是全量备份。始终能够直接还原全量备份。全量备份不依赖于完整备份之外的任何文件来保持一致性。 差异备份&#xff1a; 仅复制自…

3D展示的前景如何?

随着人类科技的不断进步&#xff0c;对未来的趋势也肯定是向高纬度发展。3D取代2D只是一个所需时间长短而已&#xff0c;题主既然这么问&#xff0c;说明肯定是意识到了3D是未来的趋势&#xff0c;那么就应该多接触和了解未来的3D平台及应用工具、应用领域等。 之前2G\3G时代&…

1.MongoDB入门指南之开篇

1. 写在前面 MongoDB大家可能听说过&#xff0c;但是要怎么学习&#xff1f;先学习哪个&#xff0c;很多人是不知道的&#xff0c;毕竟面对一个未知的事物&#xff0c;迷茫是很多人都会遇到的&#xff0c;从今天起我们就开始系统的介绍MongoDB的学习。 2. 课程介绍 课程主要分…

【Android Studio】原生应用部署第三方插件(探针)

一、本地引入包流程 &#xff08;一&#xff09;本地引入包内容 &#xff08;二&#xff09;本地引入包操作步骤 将 【probe-android-sdk】目录里面所有的aar包复制到嵌码项目工程&#xff08;App级别&#xff09;的 libs 目录下 二、添加插件 &#xff08;一&#xff09;…

Qt文件读写

Qt中文件读写类简述 包含头文件#include <QFile> 读写模式如下 枚举 文件读写步骤 1 先使用string 类型来接受打开文件的返回值 QFileDialog::getOpenFileName(this,"文件","./"); //打开一个文件 2 构建文件对象 Qfile ff (qstring)接受打…

“前缀和”专题篇一

目录 【模版】前缀和 【模版】二维前缀和 寻找数组的中心下标 除自身以外数组的乘积 【模版】前缀和 题目 思路 这道题如果使用暴力解法&#xff0c;即针对每次查询&#xff0c;先算出前r个数的总和&#xff0c;然后再算出前l-1个数的总和&#xff0c;然后相减就得出本次查…

【MYSQL】MYSQL逻辑架构

mysql逻辑架构分为3层 mysql逻辑架构分为3层 1). 连接层&#xff1a;主要完成一些类似连接处理&#xff0c;授权认证及相关的安全方案。 2). 服务层&#xff1a;在 MySQL据库系统处理底层数据之前的所有工作都是在这一层完成的&#xff0c;包括权限判断&#xff0c;SQL接口&…

三数之和-Leetcode

leetcode链接&#xff1a;三数之和 题目描述 解题思路 主要要思考以下几个问题&#xff1a; 如何选取三个元素&#xff1f;— 当前节点 左指针 右指针指针开始位置&#xff1f;— 左指针 当前节点位置 i 1&#xff0c; 右指针 n - 1如何保证不重复&#xff1f; — 先把…

利用自然语言处理(NLP)技术挖掘旅游评论数据

目录 简单了解 延伸 如何使用自然语言处理技术提高旅游评论情感倾向的准确性&#xff1f; 旅游评论数据中多模态信息融合的最佳实践是什么&#xff1f; 在旅游评论数据预处理和清洗过程中&#xff0c;哪些方法最有效&#xff1f; 使用Python网络爬虫技术进行旅游评论数据的…

Python酷库之旅-第三方库Pandas(072)

目录 一、用法精讲 291、pandas.Series.dt.round函数 291-1、语法 291-2、参数 291-3、功能 291-4、返回值 291-5、说明 291-6、用法 291-6-1、数据准备 291-6-2、代码示例 291-6-3、结果输出 292、pandas.Series.dt.floor函数 292-1、语法 292-2、参数 292-3、…

关于手机中的红外遥控

在手机电路中&#xff0c;有这么不起眼的一部分&#xff0c;虽看似简单&#xff0c;但是却给我们的生活在一定程度上带来了极大的便捷-红外遥控部分。 其置于手机顶部&#xff0c;并在壳体处挖开一个小孔&#xff0c;用于红外信号对外界的传递。如果你感兴趣的话&#xff0c;不…

Go语言项目实战班04 Go语言课程管理系统项目实战 20240807 课程笔记和上课代码

预览 课程特色 本教程录制于2024年8月8日&#xff0c;使用Go1.22版本&#xff0c;基于Goland2024进行开发&#xff0c;采用的技术栈比较新。 每节课控制在十分钟以内&#xff0c;课时精简&#xff0c;每节课都是一个独立的知识点&#xff0c;如果有遗忘&#xff0c;完全可以当…