自学C语言——函数(全)

接上一篇:自学C语言——数组(二) 

1.函数的概念

C语言中:函数=子程序

C语言中的函数就是一个完成某项特定的任务的一小段代码。

2.库函数

标准库和头文件

C语言标准中规定了C语言的语法规则,C语言不提供库函数,常用的函数称为标准库。

不同的编译器厂商根据ANSI提供的C语言标准给出的一系列函数的实现,这些函数被称为库函数。

printf

功能:

参数:

返回类型:

错误处理:

注解:

示例:

参阅:

······

 库函数的使用方法

cplusplus.com

cppreference.com _C标准库头文件

例子:(函数有使用例子,使用前要把头文件放在前边)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <math.h>
int main()
{double r = sqrt(16.0);printf("%lf\n", r);//lf.1(保留1为)return 0;
}输出:
4.000000

库函数文档的一般格式

  1. 函数原型
  2. 函数功能介绍
  3. 参数和返回类型说明
  4. 代码举例
  5. 代码输出
  6. 相关知识链接

3.自定义函数

函数的语法形式

ret_typr fun_name(   )

{

}

ret_type  函数返回类型   void表示不需要返回

fun_name 函数名

( )形式参数

{ }函数体

 例子:

//写一个加法函数,完成2个整型变量的加法操作
int Add(int x, int y)
{int z = 0;z = x + y;return z;
}int main()
{int n1 = 0;int n2 = 0;scanf("%d%d", &n1, &n2);int r = Add(n1, n2);printf("%d\n", r);return 0;
}

int main  主调函数

int Add    被调函数

简化:

{

return x + y ;

}

4.形参和实参

实参

在函数调用的时候,真实传递给函数的参数(实际参数)

例如上方的n1和n2

形参

函数定义时,函数名后边的参数就是函数的形式参数,简称形参

例如上方add中的x和y

形参和实参的关系

在调试时,形参确实得到了实参的值,但是地址不一样

在寄存器做中转,形参其实是实参的一份临时拷贝

形参是由自己独立空间的,对形参的修改,不会影响实参

  • 语法规定上,形参的名字和实参的名字可以相同
  • 形参的个数可以时没有、也可以是1个或者多个
  • 形参的个数和实参要匹配上

main函数也是函数

main函数也是被编译器指定的一个函数调用了

return 0,就是将0返回给调用main函数的那个函数

main函数中返回0表示正常返回,返回非0值表示异常返回

5.return语句

在函数设计中

  • return后边可以是一个数值,也可以是一个表达式,如果是表达式则先执行表达式,再返回表达式的结果
  • return后边也可以什么都没有,之间写return;,这种写法适合函数返回类型是void的情况
  • return返回的值和函数返回类型不一致,系统会自动将返回的值隐式转换为函数的返回类型(例如:double转化到int可能丢失数据)
  • return语句执行后,函数就彻底返回,后边的代码不再执行
  • 如果函数中存在 if 等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误(警告:“ ” 不是所有的空间路径都返回值)
void print(int n)
{if (n < 0)return;printf("hehe\n");
}int main()
{print(10);print(-10);return 0;
}
//输出
hehe
(空白)
————————————

注意:函数的返回类型如果不写的话,编译器默认int返回类型。如果返回值类型不匹配,最终返回的值的类型是不确定的。

补充:break是用在循环里的,不能代替return;

6.数组做函数参考

将数组作为参数传递给函数,在函数的内部对数组进行操作。

例:写一个函数将一个整型数组的内容,全部设置为-1,再写一个函数答应数组的内容

void set_arr(int arr[],int sz)//形参数组大小可以不写
{int i = 0;for (i = 0; i < sz; i++){arr[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 arr[] = { 1,2,3,4,5,6,7,8,9,10 };//写一个函数将数组arr的内容,全部置为-1int sz = sizeof(arr) / sizeof(arr[0]);//计算数组内元素个数print_arr(arr, sz);//先打印一边原函数set_arr(arr,sz);//打印数组内容print_arr(arr, sz);return 0;
}

 输出:

1 2 3 4 5 6 7 8 9 10
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1

问:1.为什么形参的数组不指定大小?

        答:数组传参,其实传递的是数组的地址,在形参部分访问数组的时候,其实操作的就是主调函数中的数组。

        2.set_arr中修改的数组是主函数中的arr吗?

        答:数组传参的时候,在形参的部分不会新建数组。

数组作为参数传递时,应该如何设计函数

  • 函数的形式参数要和函数的实参个数匹配
  • 函数的实参是数组,形参也可以写成数组形式的
  • 形参如果是一维数组,数组的大小可以省略不写
  • 形参如果是二维数组,行可以省略,但是列不能省略
  • 数组传参,形参是不会创建新的数组的
  • 形参操作的数组和实参的数组是同一个数组

 7.嵌套调用和链式访问

嵌套调用

嵌套调用就是函数之间的相互调用,正是应为函数之间的相互调用,才组成了大型的程序。

例:计算某年某月有多少天?

//假设我们计算某年某月有多少天?
//31 28 31 30 31 30 31 31 30 31 30 31
//   29闰年int is_leap_year(int y)//bool也行
{if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0))return 1;elsereturn 0;
}int get_days_of_month(int y, int m)
{int days[13] = {0 , 31 ,28 , 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };//              0   1   2    3    4   5   6   7   8   9  10  11  12int d = days[m];if (is_leap_year(y) && m == 2)//判断是否为闰年,如果是闰年返回1,不是闰年返回0d += 1;return d;}int main()
{int year = 0;int month = 0;scanf("%d %d", &year, &month);int day = get_days_of_month(year, month);printf("%d\n", day);return 0;
}

如果想使用 bool ,需要添加头文件 #include <stdbool.h> 

链式访问

链式访问就是将一个函数的返回值作为另一个函数的参数,像链条一样将函数串起来就是函数的链式访问。

#include<string.h>
int main()
{size_t len = strlen("abcdef");printf("%zd", len);return 0;
}
//求len的长度更简洁:
#include<string.h>
int main()
{printf("%zd", strlen("abcdef"));return 0;
}

补充:printf 函数返回的是打印在屏幕上字符的个数

#include<string.h>
int main()
{printf("%d", printf("%d", printf("%d", 43)));return 0;
}输出:4321

 上面例子中,第一个printf打印的是第二个printf的返回值,第二个printf打印的是第三个peintf的返回值

第三个printf打印43,在屏幕上打印两个字符再返回2

第二个printf打印2,在屏幕上打印一个字符再返回1

第一个peintf打印1

最终打印结果为4321

8..函数的声明和定义

单个文件

//函数的声明
int is_leap_year(int y);int main()
{int year = 0;scanf("%d", &year);//函数调用if (is_leap_year(year))printf("闰年\n");elseprintf("不是闰年\n");return 0;
}//函数定义
int is_leap_year(int y)
{return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0);
}
  • 函数定义是一种特殊的声明
  • 函数声明要在使用之前

多个文件

函数的声明一般会放在头文件( .h )中,自己写的头文件用 "  " 包含

函数的定义放在  .c  文件中

头文件封装在属性里边更改文件类型为lib静态库(动态库.dll)

使用时导入静态库#pragma comment(lib,"add.lib")

有些编译环境默认不支持多文件编译

static和extern

static 和 extern 都是C语言中的关键字。

static 是 静态的 意思,可以用来:

  • 修饰局部变量
  • 修饰全局变量
  • 修饰函数

extern 是用来声明外部符号的

#include<stdio.h>
void test()
{int a = 5;a++;printf("%d", a);}int main()
{int i = 0;for (i = 0; i < 5; i++){test();}return 0;
}输出:66666
#include<stdio.h>
void test()
{static int a = 5;a++;printf("%d", a);}int main()
{int i = 0;for (i = 0; i < 5; i++){test();}return 0;
}输出:678910

上述代码使用static时,上一次使用代码返回值会再次使用(代码运行时不执行)

结论:static 修饰局部变量改变了变量的生命周期,生命周期的改变本质是改变了变量的存储类型,本来一个局部变量是存储在内存的栈区的,但是被static修饰后存储到了静态区。存储在静态区的变量和全局变量是一样的,生命周期就和程序的生命周期一样了,只有程序结束,变量才销毁,内存才回收。但作用域是不变的。

补充:

作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效(可用)的,而限定这个名字的可用性代码范围就是这个名字的作用域。

  1. 局部变量的作用域是变量所在的局部范围。
  2. 全局变量的作用域是整个工程(项目)。

生命周期指的是变量的创建(申请内存)到变量销毁(收回内存)之间的一个时间段。

  1. 局部变量的生命周期是:进入作用域变量创建,生命周期开始,出作用域生命周期结束。
  2. 全局变量的生命周期是:整个程序的生命周期。

栈区:局部变量,形式参数

堆区:动态内存,分配,malloc,calloc,realloc/free

静态区:全局变量,静态变量

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

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

相关文章

Python异常检测- DBSCAN

系列文章目录 Python异常检测- Isolation Forest&#xff08;孤立森林&#xff09; python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子&#xff08;LOF&#xff09;算法 文章目录 系列文章目录前言一、DBSCAN算法原理二、DBSCAN算…

【小白学机器学习16】 概率论的世界观2: 从正态分布去认识世界

目录 1 从正态分布说起 1.1 正态分布的定义 1.2 正态分布的名字 1.3 正态分布的广泛&#xff0c;和基础性 2 正态分布的公式和图形 2.1 正态分布 2.2 标准正态分布 3 正态分布的认识的3个层次 3.1 第1层次&#xff1a;个体的某个属性的样本值&#xff0c;服从正态分布…

《IDE 巧用法宝:使用技巧全解析与优质插件推荐》

在日常撸代码的时候&#xff0c;相信兄弟们在IDEA 中用到不少插件&#xff0c;利用插件&#xff0c;不仅可以提高工具效率&#xff0c;撸起代码来&#xff0c;也格外的娃哈哈…… 一、IntelliJ IDEA 作为一个资深 Java 程序员&#xff0c;除了 IDEA 中默认的插件&#xff0c;我…

重学SpringBoot3-Reactive-Streams规范

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-Reactive-Streams规范 1. 什么是 Reactive-Streams 规范&#xff1f;2. Reactive-Streams 的核心组件2.1 Publisher&#xff08;发布者&#xff09;2.2 …

飞睿智能超宽带UWB音频传输模块,超低延迟数据传输,实时音频声音更纯净

在信息爆炸的时代&#xff0c;音频传输技术正以未有的速度发展&#xff0c;创新我们进入一个全新的听觉世界。今天&#xff0c;我们要探讨的&#xff0c;就是这场技术创新中的一颗璀璨明星——飞睿智能超宽带&#xff08;UWB&#xff09;音频传输模块。它以其独特的优势&#x…

光谱指标-预测含水量-多种特征提取方式

目录 1 介绍1.1 变量投影重要性&#xff08;VIP&#xff09;分析1.2. 灰色关联度&#xff08;GRA&#xff09;分析1.3. 皮尔逊相关性分析1.4 总结 2 GRA灰色关联度3 皮尔逊(Person)相关性4 变量投影重要性(Variable importance in projection&#xff0c;VIP)分析5 机器学习 1 …

webpack 老项目升级记录:从 node-sass 限制的的 node v8 提升至支持 ^node v22

老项目简介 技术框架 vue 2.5.17webpack 4.16.5"webpack-cli": "3.1.0""node-sass": "^4.7.2" 几个阶段 第一步&#xff1a;vue2 升级到最新 第一步&#xff1a;升级 vue2 至最新版本&#xff0c;截止到目前&#xff08;2024-10-…

戴维南,叠加,稳态笔记

一点点学习笔记,仅做个人复习使用 节点电压分清电流电压源&#xff0c;电流源才能写在右边&#xff0c;容易混淆 叠加定理仅适用于线性电路&#xff0c;且不能用于计算功率&#xff0c;主要是方向&#xff0c;要看源的方向判断等效之后的&#xff0c;受控源不参与除源&#x…

DMVPN协议

DMVPN&#xff08;Dynamic Multipoint VPN&#xff09;动态多点VPN 对于分公司和分总公司内网实现通信环境下&#xff0c;分公司是很多的。我们不可能每个分公司和总公司都挨个建立ipsec隧道 &#xff0c;而且如果是分公司和分公司建立隧道&#xff0c;就会很麻烦。此时我们需…

iPhone当U盘使用的方法 - iTunes共享文件夹无法复制到电脑怎么办 - 如何100%写入读出

效果图 从iPhone复制文件夹到windows电脑 步骤windows 打开iTunes通过USB连接iPhone和电脑手机允许授权iTunes中点击手机图标&#xff0c;进入到点击左边“文件共享”&#xff0c;在右边随便选择一个App&#xff08;随意...&#xff09;写入U盘&#xff1a;拖动电脑的文件&am…

随机抽取学号

idea 配置 抽学号 浏览器 提交一个100 以内的整数。&#xff0c;后端接受后&#xff0c;根据提供的整数&#xff0c;产生 100 以内的 随机数&#xff0c;返回给浏览器&#xff1f; 前端&#xff1a;提供 随机数范围 &#xff0c;病发送请求后端&#xff1a;处理随机数的产生&…

信息安全工程师(66)入侵阻断技术与应用

#1024程序员节&#xff5c;征文# 前言 入侵阻断技术是网络安全主动防御的重要技术方法&#xff0c;其基本原理是通过对目标对象的网络攻击行为进行阻断&#xff0c;从而达到保护目标对象的目的。 一、入侵阻断技术的核心原理 入侵阻断技术的核心在于对网络攻击行为的实时检测和…

震撼叶珂“假胸”引发热议黄晓明无辜躺枪

【一场关于美的争议】在这个信息爆炸的时代&#xff0c;每一个细微的风吹草动都可能成为公众关注的焦点。近日&#xff0c;一则关于叶珂“假胸”的传闻在网络上掀起了轩然大波。有网友爆料称&#xff0c;叶珂的胸部整形过度&#xff0c;甚至“隆得比肚子还大&#xff0c;都垂到…

Node + HTML搭建自己的ChatGPT [基础版]

文章目录 明明外面的ChatGPT产品那么多了&#xff0c;为什么要在本地搭建自己的ChatGPT呢&#xff1f;整体架构流程1. 获取APIKey1.1 常见的AI模型1.2 为什么选DeepSeek1.3 怎么获取DeepSeek的APIKey1.3.1 注册并登录DeepSeek开放平台1.3.2 选择API keys1.3.3 创建API key1.3.4…

VSCode编译器改为中文

1. 通过快捷键设置中文 打开命令面板&#xff1a;按住键盘上的CtrlShiftP组合键&#xff0c;打开命令面板。 输入并设置语言&#xff1a;在命令面板中输入Configure Display Language。 点击Configure Display Language选项。 在弹出的语言选择列表中&#xff0c;选择zh-cn…

node.js下载安装以及环境配置超详细教程【Windows版本】

node安装以及环境变量配置 Step1&#xff1a;选择版本进行安装Step2&#xff1a;安装Node.jsStep3&#xff1a;环境配置Step4&#xff1a;检查node.js是否成功安装Step5&#xff1a;npm修改下载镜像 Step1&#xff1a;选择版本进行安装 Node.js 安装包及源码下载地址为 Node.…

基于Spring Boot的宿舍管理系统设计与实现(源码+定制+开发)宿舍信息管理平台、智能宿舍系统开发、学生宿舍管理平台设计、宿舍入住与信息管理

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

QT-使用QSS美化UI界面

一、QSS简介&#xff1a; Qt Style Sheet&#xff1a;Qt样式表&#xff0c;用来自定义控件外观的一种机制&#xff0c;可以把他类比成CSS&#xff08;CSS主要功能与最终目的都是能使界面的表现与界面的元素分离&#xff09;。QSS机制使应用程序也能像web界面那样随意地改变外观…

vue3移动端可同时上传照片和视频的组件

uni-app中的uni-file-picker可单独上传照片或视频&#xff0c;但不支持同时上传照片和视频。本篇博客使用image标签和video标签实现移动端&#xff08;H5app小程序&#xff09;中照片和视频的同时上传。 本篇博客采用的是照片和视频的单独上传&#xff0c;但可同时展示&#xf…

Qt 学习第 天:线程与多线程

1024程序员快乐&#xff0c;如果这博客让你学习到了知识&#xff0c;请给我一个免费的赞❤️ 一、创建界面文件 LCDnumber 二、创建mythread类&#xff0c;继承QObject 三、在MyThread.h文件做修改&#xff0c;并且加上函数声明 引入头文件&#xff0c;改变继承 #ifndef MY…