函数的介绍
1.函数的概念
在C语言中也有函数的概念,有些翻译为:子程序,这种翻译更为准确。C语言的函数就是一个完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。
C语言的程序其实是有无数个小的函数组合而成的,也可以说:一个大的计算任务可以分解成若干个较小的的函数完成。同时一个函数如果能完成某项特定任务的话,这个函数也是可以复用的,提升了开发软件的效率。
在C语言中一般会见到的两类函数:
- 库函数
- 自定义函数
2.库函数
2.1标准库和头文件
C语言标准库中规定了C语言的各种语法规则,C语言并不提供库函数,C语言的国际标准ANSI C规定了一些常用的函数的标准,被称为标准库,那不同的编译器厂商根据ANSI提供的C语言标准就给出了一系列函数的实现。这些函数被称为库函数。
前面内容中学到的 printf 和 scanf 都是库函数,库函数也是函数,不过这些函数已经是现成的,我们只要学会就能直接使用了。有了库函数,一些常见的功能就不需要我们自己写了,在一定程度上提升了效率;同时库函数的质量和执行效率上都更有保证。
各种编译器的标准库中提供了一系列的库函数,这些库函数根据功能划分,都在不同的头文件中进行了声明。
2.2库函数的使用方法
2.2.1头文件的包含
库函数是在标准库中对应的头文件中声明的,所以库函数的使用,应该包含对应的头文件,不包含是可能会出现一些问题。
#include<stdio.h>
#include<math.h>
int main()
{double ret = sqrt(16.0);printf("%lf\n", ret);return 0;
}
输出结果:

3.自定义函数
了解了库函数,其实自定义函数更加重要。
3.1函数的语法形式
自定义函数和跨函数是一样的,形式如下:
type name(形式参数)
{
}
- type 是函数返回类型
- name 是函数名
- 括号中是放形式参数
- { }括起来的是函数体
type 是用来表示函数计算结果的类型,有时候返回的类型可以是 void ,表示什么都不返回
name 是为了方便使用函数,就像人一样,有了名字方便称呼,而函数有了名字方便调用,所以函数名尽量根据函数的功能起的有意义。
函数的参数也可以是 viod ,明确表示函数没有参数。如果没有参数,要交代清楚参数的类型和名字,以及参数的个数。
3.2函数的例子
写一个加法函数,完成2个整型变量的加法操作。
int Add(int x, int y)
{return x + y;
}int main()
{int a = 0;int b = 0;scanf("%d %d", &a, &b);int ret=Add(a, b);printf("%d\n", ret);return 0;
}
我们给函数取名为:Add ,函数 Add 需要接收2个整型类型的参数,函数计算的结果也是整型。
4.形参和实参
在函数使用过程中,把函数的参数分为:实参和形参
4.1实参
在上面的代码中,main 函数中的 a,b称为实际参数,简称实参。实际参数就是真实传递给函数的参数。
4.2形参
在上面代码中,函数名 Add 后括号中的 x 和 y ,称为形式参数,简称形参。
为什么是形式参数呢?实际上,如果只是定义了 Add 函数,而不去调用的话,Add 函数的参数 x 和 y 只是形式上存在,不会向内存申请空间,不会真实存在,所以叫做形式参数。形式参数只有在函数被调用的过程中为了存放实参传递过来的值,才会向内存申请空间,这个过程就是形参的实例化。
4.3实参和形参的关系
虽然我们提到了实参是传递给形参的,他们之间是有联系的,但是形参和实参各自是独立的内存空间。

在上面的调试中可以看见虽然 x 和 a 的值相等,但是可以发现两个的地址不一样,同样 y 和 b 也是值一样,地址不一样。所以我们可以理解为形参是实参的一份临时拷贝。
5.return语句
在函数的设计中,函数中经常会出现 return 语句,return 语句的注意事项:
- return后边可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果。
- return后边也可以什么都没有,直接写 return ;这种写法适合函数返回类型是void的情况。
- return返回的值和函数返回类型不一致,系统会自动将返回类型的值转换为函数的返回类型。
- return 语句执行后,函数就彻底返回,后边的代码不再执行。
- 如果函数里面存在 if 等分支语句,则要保证每种情况下都有 return 返回,否则会出现编译错误。
6.数组做函数参数
在使用函数解决问题时,可能会将数组作为参数传递给函数,在函数内部对数组进行操作。
例如:写一个函数将一个整型数组内容全部置为 -1:
void set_arr(int arr2[],int sz2)
{int i = 0;for (i = 0; i < sz2; i++){arr2[i] = -1;}
}
void print_arr(int arr[], int sz) {int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}int main()
{int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz1 = sizeof(arr1) / sizeof(arr1[0]);//打印数组的所有内容print_arr(arr1,sz1);//将数组里面的元素全部设置为-1set_arr(arr1,sz1);print_arr(arr1, sz1);return 0;
}
7.嵌套调用和链式访问
7.1嵌套调用
嵌套调用就是函数之间的相互调用,正是因为函数的相互调用,最后才写出了大型的程序。
例如:实现输入的某年某月有多少天?
get_year(): 来判断是否为闰年
get_days(): 调用get_year确定是否为闰年后,再根据月份来计算这个月有多少天?
//判断是否为闰年
int get_year(int year)
{if (((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0)))return 1;elsereturn 0;
}int get_days(int y, int m) {int arr[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };int day = arr[m];if (get_year(y) && m == 2)//闰年返回1{day++;}return day;
}
int main()
{int year = 0;int month = 0;scanf("%d %d", &year, &month);int d = get_days(year, month);printf("%d\n",d);return 0;
}
7.2链式访问
链式访问就是将一个函数的返回值作为另一个将函数的参数,像链条一样将函数串起来就是函数的链式访问。
int main()
{/*size_t len = strlen("abcdef");printf("%zd\n", len);*/printf("%zd\n", strlen("abcdef"));return 0;
}
可以从上面的代码中看见,将注释了的两行代码转换为一条语句,这里就构成了函数的链式访问。
int main()
{printf("%d", printf("%d", printf("%d", 43)));
// 打印1 打印2返回1(1个字符) 打印43,返回2(2个字符)
//输出结果为 4321printf("%d ", printf("%d ", printf("%d ", 43)));
//中间加了空格则输出结果为:43 3 2(空格也算是一个字符)
}
8.函数的声明和定义
8.1单个文件
一般我们使用函式的时候,直接将函数写出来就使用了。
例如:判断一年是否为闰年的代码:

红色框里面是函数的定义,而绿色框里面是函数的调用。
这样的顺序没有什么问题,当我们将定义放在调用之后就会出现问题。

就会有这样的错误:

这是因为C语言编译器对源代码进行编译时,从第一行往下扫描,但遇到第251行 is_leap_year调用时,在前面并没有发现 is_leap_year 函数的定义,就会报出上面的警告。
解决的方法:
- 将函数的定义写在函数调用的前面
- 在函数调用之前写上函数的声明

- 函数的调用一定要满足:先声明后调用,有时函数的定义是需要写在后面的,这时我们就可以用函数的声明
- 函数的定义也是一种特殊的声明,所以函数的定义放在调用之前也是可以的。
8.2多个文件
一般情况下,函数的声明和类型的声明放在头文件中,函数的实现会放在源文件中。

分模块写代码的好处:
- 逻辑清晰
- 方便写作
8.3 static 和 extern
static 和 extern 都是C语言的关键字。
static 是静态的意思,可以用来:
- 修饰局部变量
- 修饰全局变量
- 修饰函数
extern 是用来声明外部符号的。
在了解 static 和 extern 之前先了解一下:作用域 和 生命周期
作用域 是程序设计的概念,通常来说,一段程序代码中所用到的名字并不总是有效(可用)的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
- 局部变量的作用域时变量所在的局部范围。
- 全局变量的作用域是整个项目。
生命周期 指的是变量的创建(申请内存)到变量的销毁(收回内存)之间的一个时间段。
- 局部变量的生命周期是:进入作用域变量的船舰,生命周期开始,出作用域生命周期结束。
- 全局变量的生命周期是:整个程序的生命周期。
8.3.1 static 修饰局部变量:
int test()
{int i = 0;i++;printf("%d ", i);
}int main()
{int i = 0;for (i = 0; i < 5; i++) {test();}return 0;
}
int test()
{static int i = 0;i++;printf("%d ", i);
}int main()
{int i = 0;for (i = 0; i < 5; i++){test();}return 0;
}
将上面的两组代码进行对比的话就可以更好的体现出 static 修饰局部变量的作用。
代码1中的test函数中的i属于局部变量,当主函数调用 test 函数时,局部变量i开始创建,生命周期开始,之后++,再打印,出函数时变量的生命周期结束,释放内存。
代码2中其实运行一下结果就可以发现具有累加的作用,其实主函数调用test函数时变量创建,出函数时也不会被销毁,重新进入函数也不会再次创建变量,直接上次累积的值上面进行计算。
结论:
static 修饰局部变量改变了变量的生命周期,生命周期改变的本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,当被 static 修饰后就存储到了静态区。存储到静态区的变量和全局变量一样,生命周期就和程序的生命周期一样了,只有程序结束,变量才会销毁,内存才回收,但是作用域不变。
内存:

建议:如果一个变量出了函数之后,我们还想保留值等下次进入函数继续使用,就可以使用static来修饰。
8.3.2 static 修饰全局变量

当我们这样写时输出结果为:2018;而当我们在全局变量的前面加上 static'时,此时的结果又是怎样的呢?

此时就会出现(链接型错误)报错,这是因为:extern 是用来声明外部符号的,如果一个全局的符号在X文件中定义的,在Y文件中想使用的,就可以使用 extern 来进行声明后再使用。
结论:
一个全局变量被static修饰,使得这个全局变量只能在本源的文件中使用,其他文件不能使用。
本质原因是全局变量默认是具有外部链接属性的,在外部文件中想使用,只要适当的声明就可以使用,但是全局变量被static修饰后,外部连接属性就变成里的内部链接属性,只能在自己所在的文件中使用,其他文件就算是进行了声明也无法正常使用。
建议:
如果一个全局变量只想在所在的文件中使用,不想被其他文件使用是,就可以使用static来修饰全局变量。
8.3.3 static 修饰函数


我们可以发现:其实static修饰函数和static修饰全局变量是一模一样的,一个函数在整个工程都可以被使用,但是当被 static 修饰时,只能在本文件中使用,其他文件无法使用。
建议:
一个函数只想在本文件中被使用,不想被其他文件使用,就可以用 static 来修饰。
相关文章:
函数的介绍
1.函数的概念 在C语言中也有函数的概念,有些翻译为:子程序,这种翻译更为准确。C语言的函数就是一个完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。 C语言的程序其实是有无数个小的函数组合而成的,也可以…...
源自Deformable Convolutional Networks的一种可变形卷积实现解析
衍生记录:深度学习pytorch之简单方法自定义9类卷积即插即用 文章目录 概述1. 可变形卷积的背景2. DeformConv2D概述2.1 构造函数分析2.2 前向传播函数解析2.2.1 偏移量的计算与应用2.2.2 目标位置的计算2.2.3 四个角的插值2.2.4 双线性插值的权重2.2.5 特征图的采样…...
记一次性能调优-20250320
2月份年后上班,刚过完年,还没从喜悦中解放出来,凌晨3点的时候同事就给我打电话,晚上的批量处理任务卡住了,快帮忙看看,做了几分钟的心里建设之后从被窝爬起来,看着手机上好几电话,赶…...
Postman高级功能深度解析:Mock Server与自动化监控——构建高效API测试与监控体系
引言:Postman在API开发中的核心价值 在数字化时代,API(应用程序编程接口)已成为系统间交互的“神经网络”,其质量直接影响用户体验与业务连续性。然而,传统API测试面临两大挑战: 开发阶段依赖…...
【最后203篇系列】020 rocksdb agent
今天还是挺开心的一天,又在工具箱里加了一个工具。嗯,但是快下班的时候也碰到一些不太顺心的事,让我有点恼火。我还真没想到一个专职的前端,加测试,以及其他一堆人,竟然不知道后端返回的markdown,在前端渲染…...
OpenCV旋转估计(2)用于自动检测波浪校正类型的函数autoDetectWaveCorrectKind()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::detail::autoDetectWaveCorrectKind 是 OpenCV 中用于自动检测波浪校正类型的函数,它根据输入的旋转矩阵集合来决定使用哪种波浪…...
mysql-connector-python 报错(0xC0000005)
报错情况: 原因: mysql-connector-python版本不对,我们的mysql版本为sql8.0需要下载mysql-connector-python8.0....的库 方法: pip install mysql-connector-python8.1.0 即可...
从零开始实现Stable Diffusion本地部署
1. 依赖安装 文件打包下载地址(Stable Diffusion) # git : 用于下载源码 https://git-scm.com/downloads/win # Python 作为基础编译环境 https://www.python.org/downloads/ # Nvidia 驱动,用于编译使用GPU显卡硬件 https://ww…...
RAG各类方法python源码解读与实践:利用Jupyter对RAG技术综合评测【3万字长文】
检索增强生成(RAG )是一种结合信息检索与生成模型的混合方法。它通过引入外部知识来提升语言模型的性能,从而提高回答的准确性和事实正确性。为了简单易学,不使用LangChain框架或FAISS向量数据库,而是利用Jupyter Note…...
transform C++标准库算法用法(对容器中元素进行转换操作:大小写转换、向量的加法乘法运算)
std::transform 是 C 标准库中的一个算法,用于对容器(如数组、向量、字符串等)中的元素进行转换操作,并将结果存储到指定的目标位置。它可以对单个范围或两个范围的元素进行操作,并将结果写入另一个容器。 1. 头文件 …...
Java File 类与文件操作
一、引言 在 Java 编程中,文件操作是一项非常常见且重要的任务。无论是读取配置文件、保存用户数据,还是进行日志记录,都离不开对文件的操作。Java 提供了 File 类来表示文件和目录的抽象路径名,通过该类可以对文件和目录进行创建、删除、重命名等操作。同时,Java 还提供…...
Python 字符串的编码格式
在 Python 中,字符串(str)默认使用 Unicode 编码,具体来说,Python 3 中的字符串是以 UTF-8 编码存储的 Unicode 字符序列。Unicode 是一种国际标准,旨在为世界上所有的字符提供唯一的编码,而 UTF-8 是 Unicode 的一种实现方式,具有兼容性和高效性。 1. Unicode 与 UTF-…...
RPA+AI 技术到底好在哪里?
在自动化领域,RPA与生成式AI都是强大的技术,都可以用来实现自动执行重复耗时的任务。 主要区别是:传统RPA擅长处理结构化与规则明确简单的流程,而在非结构化数据处理、动态上下文适应、智能决策等能力上有欠缺;而基于…...
flowable适配达梦7 (2.1)
经过第一版的问题解决,后端项目可以启动,前端页面也集成进去。 前端在流程设计页面报错 之后发现主要是组件中modelerStore这个值没有 解决方法:在data增加对象 给component/process/designer.vue 中涉及到的每个子组件传入 :modelerStore“modeler…...
基于java的ssm+JSP+MYSQL的母婴用品网站(含LW+PPT+源码+系统演示视频+安装说明)
系统功能 管理员功能模块: 主页 个人中心 用户管理 商品分类管理 商品信息管理 留言板管理 成长交流 系统管理 订单管理 留言管理 用户功能模块: 主页 个人中心 我的收藏管理 订单管理 前台首页功能模块: 首页 商品信息 论…...
面试八股 —— Redis篇
重点:缓存 和 分布式锁 缓存(穿透,击穿,雪崩) 降级可作为系统的保底策略,适用于穿透,击穿,雪崩 1.缓存穿透 2.缓存击穿 3.缓存雪崩 缓存——双写一致性 1.强一致性业务(…...
gradle-8.13
gradle-8.13 稍微看了下,基于Maven改造的 https://gradle.org/install/https://github.com/gradle/gradle-distributions/releaseshttps://github.com/gradle/gradle-distributions/releases/download/v8.13.0/gradle-8.13-all.zip https://github.com/gradle/gra…...
不使用负压电源,ADC如何测量正负压?
电路图来自ZLinear的开源数据采集板卡DL8884_RFN,是一个比较常见的电压偏置采集法 对电路进行分析,所以说可以先看下采集卡的模拟输入部分的参数如下: 通道数量: 8通道单端输入/4通道差分输入 分辨率: 16位逐次逼近型(SAR) ADC 采样速率: 40…...
在 Linux 系统上部署 Deepseek AI 的全面指南
对于所有希望亲身体验 AI 魅力的玩家来说,本文将提供一个详尽的教程,指导你在 Linux 系统上部署 Deepseek AI。无论你是技术小白还是有一定基础的用户,都能轻松跟随本文完成部署。 一、关于 Ollama Ollama 是一款功能强大的开源应用&am…...
SinoSteel生产企业ERP实施建议书final(143页PPT)(文末有下载方式)
资料解读:SinoSteel 生产企业 ERP 实施建议书 final 详细资料请看本解读文章的最后内容。 在当今竞争激烈的商业环境中,企业的信息化建设对于提升竞争力和实现可持续发展至关重要。中钢集团作为一家大型跨国企业集团,在钢铁行业占据重要地位。…...
贴片陶瓷天线和蓝牙天线的layout注意事项
板载天线,也有封装成器件进行使用: 看到这里,细心的人发现,天线接入芯片的时候,旁边也直接接地了: F型天线(Inverted F Antenna, IFA)的一端接地,看起来像是“短路”&am…...
关于波士顿动力2025年3月的人形机器人最新视频
这是完整的视频: 波士顿动力最新逆天表演-机器人Atlas行走、奔跑、爬行、杂技_哔哩哔哩_bilibili 至少从目前来看,综合对比运动的幅度、各关节的协调性、整体的顺遂性、动作的拟人程度,波士顿动力是已知人形机器人中最好的。 尤其需要关注…...
fontTools工具的使用介绍
前言 python工具库fontTools,我是用来压缩前端字体的,优化前端请求速度的;使用的过程中,遇到了不少的坑,把这个过程记录下来,防止再犯。 安装 # fontTools 4.56.0 pip install fontTools提取子字体集 方…...
深入理解计算机网络:OSI 与 TCP/IP 各层结构与功能
目录 1. 引言 2. OSI 模型 2.1 OSI 各层的详细功能 2.1.1 物理层 2.1.2 数据链路层 2.1.3 网络层 2.1.4 传输层 2.1.5 会话层 2.1.6 表示层 2.1.7 应用层 3. TCP/IP 模型 3.1 TCP/IP 各层的详细功能 3.1.1 网络接口层 3.1.2 网络层 3.1.3 传输层 3.1.4 应用层 …...
Wi-Fi NAN 架构(Wi-Fi Aware Specification v4.0,第2章:2.3~2.6)
1. NAN 数据通信架构 1.1 单播支持 要在两个NAN设备之间启动单播数据通信,服务需发起一个NAN数据路径(NDP,NAN Data Path)请求。这对NAN设备之间会建立一个NAN设备链路(NDL,NAN Device Link)&…...
Arduino示例代码讲解:Multiple tone player 多音播放器
Arduino示例代码讲解:Multiple tone player 多音播放器 Multiple tone player 多音播放器代码功能代码逐行解释1. 注释部分2. `setup()` 函数3. `loop()` 函数硬件连接**扬声器连接**:**Arduino板**:运行结果修改建议关于`tone()`和`noTone()`函数视频讲解Multiple tone pla…...
Windows电脑 打开 Docker Desktop 提示的“Virtual Machine Platform not enabled”的问题解决
文章目录 问题来源解决方案 问题来源 因为要在本地推送 docker 镜像 到镜像库,所以安装了 Docker Desktop ,刚开始是好的,后来因为要调试 uniapp 安卓App,又装了雷电模拟器。然后就冲突了,打不开 Docker Desktop了&am…...
【愚公系列】《高效使用DeepSeek》020-专业术语解释
🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...
1.环境搭建VUE+Spring boot
一.vue 环境搭建 Spring Boot 和 Vue,可以实现前后端分离的架构,提高开发效率和应用性能。Spring Boot 负责后端逻辑和数据处理,Vue 负责前端展示和用户交互。 1.1安装node.js 这个是是安装在个人电脑上 直接在官网下载然后安装即可&…...
第二十七篇 数据仓库与维度建模指南:从理论到实战的进阶之路
声明:文章内容仅供参考,需仔细甄别。文中技术名称属相关方商标,仅作技术描述;代码示例为交流学习用途,部分参考开源文档(Apache 2.0/GPLv3);案例数据已脱敏,技术推荐保持…...
