函数(C语言)

1:函数的概念

        函数的概念我们在初中的时候就已经听过了。

        在C语言中也引入了函数,也可以叫子程序

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

        这段代码是有特殊的写法和调用方法的。其实C语言的程序也是由无数个小的函数组成的。

        也就是,一个大的项目可以拆成好几个小的项目完成。

        还有就是对于一个需要经常使用到的功能,函数的复用也提高了开发的效率。3

       在C语言中我们一般会见到两类函数

       1:库函数

       2:自定义函数

2:库函数  

       对于库函数我们可以进入这个链接学习,这种用的多了就记住了,不过得注意的是使用库函           数的时候要包含头文件

       链接:https://zh.cppreference.com/w/c/header


3:自定义函数

     3. 1:函数的语法形式

              ret_type   fun_name(形式参数){}

              ret_type:是函数返回类型

              fun_name:是函数名

              括号里面是形式参数

              {}里面的是函数体

              我们可以把函数当成一个加工厂,工厂输入原材料,经过工厂加工才能生产出产品,那                  函数也是一样,函数一般会输入一些值(可以是0个,也可以是多个),经过函数内的计                算,得出结果。

             5ccf71b2567048e685d5b5a339c74e81.png

            注: 1、ret_type是用来表示函数计算结果的类型,有时候返回类型可以是void,表示什么                            都不返回。

                    2、fun_name是为了方便使用函数;就像人的名字一样,函数名字的取法可以根据其                            实现的功能有关来取,这样更有意义。也可以提高代码的可读性。

                    3、函数的参数相当于送进厂里的原材料一样,经过函数的计算得出结果。函数的参                              数也可以是void,表示函数没有参数。如果有参数,要交代清楚参数的类型和名                              字,以及参数的个数。

                    4、{}括起来的就是函数体,函数体就是完成整个计算的过程。

 

       3.2:函数的举例 

               例:写一个加法函数,实现两个数相加

d437781b85d6459896647f08a60753e5.png               

     如上我们根据要求可以得知需要返回的值为一个整数类型,所以定义的函数类型也为整

     然后我们可以根据实现的功能来取名,是要实现一个整数加法,所以取名add,然后是要实现         两个整数的加法,所以形参设置为两个整型数据。然后返回的是两个参数的加法结果。

4:实参和形参

     在函数中我们把参数分为实参和形参

     4172ef0bc39d43a68a49b06de539ebca.png

   4.1:实参

           在上面的代码中第3~7行就是对函数的定义语句,有了函数后,我们在main函数内调用函               数,在调用函数后,将x,y的值传给函数add,这个x,y就是实参了。称为实际参数,简称实               参。实际参数就是真实传递给函数。

4.2:形参

         在上面代码中对于函数的定义部分。函数名后面括号里面的的x,y就是形式参数,简称形参。

         实际上,如果只是定义了add函数,而不去调用的话,add函数的参数x和y只是形式上存在,

         不会向内存申请空间,是不会真实存在的,所以叫做形式参数。形式参数只是在函数在被调           用的过程中为了存放实际参数传递过来的值,猜才会向内存申请空间,这个过程也叫形参的           实例化。

4.3:形参和实参的关系

        虽然提到了实参是传递给形参的,那么他们之间也应该有联系。但是形参和实参之间是独自            的内存空间,我们可以通过调试下面的代码来看一下。

       958967b855d840fd92556a24fe5107e2.png

        

          383866f9bb92414b9b36a5bbcb72eb37.png

             

    我们在对上面的代码进行调试可以观察到,x和y确实得到了a和b的值,但是x和y的地址和a,b的      地址是不一样的 ,所以我们可以确认的是形参是实参的临时拷贝。

 

5:return语句

        在函数的设计中,函数经常会出现return语,我们要注意一些return的问题

        1、return后边可以是一个值,也可以是一个表达式,如果是表达式则会先执行表达式,再返               回表达式的结果

        2、return后边也可以什么都没有,写成return;这个样子,这种写法适合函数返回类型是void               的情况

        3、return的返回值和函数的返回类型不一样,系统会自动将返回的值转换成函数的返回类                    型。

        4、return语句执行后,函数就彻底返回,后面的代码就不会再执行了

        5、如果函数中存在if分支语句,则要保证每种情况下都有return返回,否则会出现编译错误。

 

6:数组做函数参数

     在使用函数中,我们难免会使用到数组做函数的参数,在函数内部对数组进行一些操作。

     比如:写一个函数将一个整型数组的内容,全部置为-1,再写一个函数打印数组的内容。

     其基本形式如下:b8b415d0511547ceb3023c2c14bbfc5a.png

    04d409a24b56467aae356e559aea2182.png

                      

   上面可以看到需要对数组进行操作,就得把数组作为参数传递给函数,同时函数在定义的时候也     要设置一个形参为数组。但是可以看到,在定义函数的时候,是要把数组形参那个部分设置成和     定义数组的时候一样,而在调用函数的时候只需要将数组名放在对应的位置即可。

   下面为数组作为参数时要注意的:

   1、函数的形参个数要和函数的实参个数匹配

   2、函数的实参是数组,形参也是可以写成数组形式的

   3、形参如果是一维数组,那么数组大小可以不写

   4、形参如果是二维数组,行可以省略,列不可以3

   5、数组传参,形参是不会创建一个新的数组的

   6、形参操作的数组和实参的数组是同一个数组

 

7:嵌套使用和链式访问

7.1:嵌套调用

         函数的嵌套使用就是函数之间的互相调用。下面我们通过一个实例来理解这个只知识

        例:假设我们计算某年某月有多少天?要使用函数来实现,可以设计下面两个函数

              1、is_leap_year():根据年份来确定是不是闰年

              2、get_days_month():调用is_leap_year()确实是否是闰年后,再根据月份计算天数

              8e50ca3b3234485fb8354b90ac1eb6d8.png

         上面的程序可以看到,我们在main函数中调用了scanf,printf,get_days_of_month函数

         get_days_of_month函数中我们调用了is_leap_year函数

         这就是嵌套使用函数。在后面的学习中我们需要经常这样使用函数。

 7.2:链式访问

         将一个函数的返回值作为另一个函数的参数,像一条链条一样将函数串起来就是函数的链式           访问。比如下面的代码:

         736e99ffefbd4eb4baa0b37024177532.png

         上面的代码printf函数将get_days_of_month函数的返回值作为参数使用

         下面我们来通过函数的链式访问写一个有趣的代码:

          e59995266024484dae276f932d949c6d.png

         可以看到这个链式访问的在屏幕上打印了4321。

         这个代码的关键是要知道printf函数返回的是啥。

         printf函数返回的是其打印的字符个数。所以对于上面代码的解读为:

         第三个printf函数打印43是打印两个字符,所以返回值是2

         第二个printf函数打印的是第三个printf的返回值,则打印2

         第一个就打印第二个printf函数的返回值1 

         所以连起来就是4321了。

8:函数的声明和定义

8.1:单个文件

          一般我们在使用函数的时候都是直接把他写出来然后就使用了

          比如下面的函数:

          f9200c9d203447a7a52a2aae70de416e.png        

        上面橙色的部分是函数的定义,绿色的部分是函数的调用部分,这种场景下函数的定义在调            用前,这种是没啥问题的。

        如果我们将函数的定义放在函数调用后面

        4314ffd91dba408abc966c8bdaa846d5.png

 

    可以看到在错误一栏看到有下面的错误信息:

    8ade8da724b84c5d85c38adbb0ca2112.png

    这就是程序在运行的时候,从第一行开始,到调用这个函数的时候,并没有在前面发现这个函        数所以做出了这个警告。

    我们要在使用这个函数前对函数进行声明一下,就是告诉编译器我们有这么一个函数。

    声明只需要交代清楚函数的返回数据类型,参数,名字就可以。

 a6d751b3cf4442298b0b17f5015f3d05.png

         这样程序就可以正常使用了。.

         函数的声明一定要在函数调用前,先声明后使用。

         函数的定义是一种特殊的声明,所以函数的定义放在调用前也是可以的。

 

8.2:多个文件

        一般企业在开发中,代码量就非常大了,这时候就肯定不会将代码都放在一个文件中,往往            会根据程序的功能,将代码拆分放在多个文件中。

        一般情况下,函数的声明,类型的声明会放在头文件.h内,函数的实现是放在源文件.c中

        如下:

       函数声明:在.h文件中f3e7c4edbade47689f8f53b319e43a1b.png

      函数的定义放在源文件.c中:e7704ed21a064868883b5bbd30a6e5a4.png

        随后我们要使用这个函数,则需要包含这个头文件,自己定义的,只需要用引号引起来即              可:

 cb3b7370289d40d2bcf80ef346a9d5a0.png

         这个时候就可以运行了

 8.3:static和extern

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

          static是静态的意思,其有如下的用途:

          1、修饰局部变量

          2、修饰全局变量

          3、修饰函数

          extern是用来修饰外部符号的

         在学习这两个关键字前我们需要对作用域和生命周期进行了解

         作用域:是程序设计的概念;一段程序代码中使用到的名字不总是有效的(可用)

                       而限定这个名字的可用性的代码范围就是这个名字的作用域。

                      1、局部变量的作用域就是变量所在的局部范围

                      2、全局变量的作用域是整个工程(项目)

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

                            1、局部变量的生命周期为:进入作用域变量创建,生命周期开始,出作用域生                                    命周期结束。

                            2、全局变量的生命周期是整个程序的生命周期

          8.3.1:static修饰局部变量

                      683e3c0991374697bffe3a3bf676715b.png

                         通过代码1和代码2的区别来理解static的效果

                         代码1的test函数中的局部变量i是每次进⼊test函数先创建变量(⽣命周期开始)                             并赋值为0,然后 ++,再打印,出函数的时候变量⽣命周期将要结束(释放内存)。

                        代码2中,我们从输出结果来看,i的值有累加的效果,其实test函数中的i创建好                            后,出函数的时候是 不会销毁的,重新进⼊函数也就不会重新创建变量,直接上                            次累积的数值继续计算

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

                       使⽤建议:未来⼀个变量出了函数后,我们还想保留值,等下次进⼊函数继续使                                               ⽤,就可以使⽤static 修饰。

 2、static修饰全局变量

                        一个全局变量被static修饰的话,会使得这个变量只能在本源文件中使用,不能在                           其他源文件使用,是因为全局变量默认是有外部链接属性的,在外部文件中想使                             用,只需要做适当的声明就可以了的,但当有static修饰后,外部链接属性就变成了                         内部链接属性,就只能在自己所在的源文件使用了,其他的源文件即使声明了也是                         无法使用的。

                       使用建议:如果一个全局变量,只想在所在的源文件内部使用,不想被其他文件发                                          现和使用,可以使用static修饰。

3、static修饰函数

                        static修饰函数和修饰全局变量是差不多的,也是使得函数只能在所在的源文件使                            用,不能在其他的文件上使用。

                       使用建议:一个函数只想在所在的源文件内部使用,不想在其他源文件使用,就可                                          以使用static修饰

8.3.2:extern关键字

                       extern是用来声明外部符号的,如果一个全局变量在文件A中定义,然后B文件中需                        要使用,我们就可以使用extern来修饰,这样就可以使用了。

                    

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=6c6da1gg1x0b

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

VMWare安装包及安装过程

虚拟机基本使用 检查自己是否开启虚拟化 如果虚拟化没有开启,需要自行开启:百度加上自己电脑的品牌型号,进入BIOS界面开启 什么是虚拟机 所谓的虚拟机,就是在当前计算机系统中,又开启了一个虚拟系统 这个虚拟系统&…

基于SVD奇异值分解的图像压缩算法(Python实现)

前言 SVD其实和PCA类似,就是丢入一个特征矩阵 X ,输出另外一个特征矩阵 X′ , X′ 的维度要比原来的X 要低。并且里面的变量都是原来的变量的线性组合,所以含义也变得不好解释。 简单来说就是数据压缩,特征降维的一种技术&#…

国产AI图片工具,全部免费亲测实用!

近AI生图功能火出圈了,各家大厂都拿出了看家本领,今天就来聊聊即梦AI、通义万相、奇域AI和腾讯元宝的AI生图功能,看看它们各有什么特色吧! 一、Dreamina 字节旗下的AI智能平台,简单实用的图片生成,对中国元…

C++ 二叉搜索树

二叉搜索树的概念 二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树: 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右…

推荐一款3D建模软件:Agisoft Metashape Pro

Agisoft Metashape Pro是一款强大的多视点三维建模设计辅助软件,Agisoft Metashape是一款独立的软件产品,可对数字图像进行摄影测量处理,并生成3D空间数据,用于GIS应用,文化遗产文档和视觉效果制作,以及间接…

IntelliJ+SpringBoot项目实战(四)--快速上手数据库开发

对于新手学习SpringBoot开发,可能最急迫的事情就是尽快掌握数据库的开发。目前数据库开发主要流行使用Mybatis和Mybatis Plus,不过这2个框架对于新手而言需要一定的时间掌握,如果快速上手数据库开发,可以先按照本文介绍的方式使用JdbcTemplat…

Linux高阶——1110—线程安全问题解决方法

1、同步、异步、阻塞、非阻塞 同步过程:发起调用,调用者需要等待被调用者的结果 异步过程:发起调用,无需等待被调用的结果,当有结果后,此结果传出,无需主动获取 阻塞和非阻塞:发起…

STM32cubemx+Proteus仿真和keil5联合调试

前面两步 STM32cubemx生成代码 https://blog.csdn.net/weixin_52733843/article/details/143637304 Proteus新建工程 https://blog.csdn.net/weixin_52733843/article/details/143578853 1 *Proteus仿真联合调试* 在Proteus中,双击STM32F103C6芯片&#xff0c…

初识算法 · 位运算常见总结(1)

目录 前言: 位运算基本总结 部分题目代码 前言: ​本文的主题是位运算,通过常见的知识点讲解,并且会附上5道简单的题目,5道题目的链接分别为:191. 位1的个数 - 力扣(LeetCode) 1…

visualvm远程连接Docker容器中部署的java应用并监控

visualvm远程连接Docker容器中部署的java应用 前言 jdk1.8中自带了,java11中需要单独下载 下载地址 visualvm下载地址 简介 java虚拟机监控,故障排查及性能分析工具。 网络配置 局域网与docker内网打通,请参考:办公网络与Docker内…

NVIDIA RTX 系统上使用 llama.cpp 加速 LLM

NVIDIA RTX 系统上使用 llama.cpp 加速 LLM 文章目录 NVIDIA RTX 系统上使用 llama.cpp 加速 LLMllama.cpp 概述llama.cpp 在 NVIDIA RTX 上的加速性能使用 llama.cpp 构建的开发人员生态系统使用 llama.cpp 在 RTX 平台上加速的应用程序开始使用 适用于 Windows PC 的 NVIDIA …

信息收集系列(二):ASN分析及域名收集

内容预览 ≧∀≦ゞ 信息收集系列(二):ASN分析及域名收集前言一、ASN 分析1. 获取 ASN 码2. 使用 ASNMap 获取 IP 范围3. 将 IP 范围转化为 IP 列表 二、关联域名收集1. 顶级域(TLD)收集测试方法 2. 根域名收集常用方法…

揭秘:b站可以通过弹幕查询到发送者吗?答案是:不可行

查找发送者 发弹幕被找到 最近,我的一个好兄弟遇到了这样一个问题:他在b站发弹幕,结果被人找到了。他对此很困惑:“发送弹幕不是匿名的吗?只有评论才能看到用户名啊,难道发弹幕也可以被找到吗&#xff1f…

安装mysql、Navicat 17

1.安装mysql 下载地址 https://downloads.mysql.com/archives/installer/ 选择最新版本或者你需要的版本 点击第二个Download下载 下载完毕后双击启动,之后是这个页面 选Custom(第四个)自定义安装,可以将mysql安装到自定义目录…

人工智能助手是否让程序员技能退化?

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

RecyclerView进阶知识讲解

在 Android 开发中,RecyclerView 是一种高效的列表和网格布局控件,用于显示大规模数据。尽管基本使用方法简单,但深入理解并掌握其高级进阶用法能大幅提升用户体验和应用性能。下面,我将从布局管理、动画和手势、自定义缓存、优化…

测试用例设计方法之判定表

测试用例设计方法之判定表 1. 为什么要有判定表方法2. 什么是判定表3. 判定表法设计用例步骤4. 判定表使用场景 1. 为什么要有判定表方法 案例: 验证"若用户欠费或者关机, 则不允许主被叫"功能的测试 说明: 等价类和边界值分析法主要关注单个输入类条件的测试并未考…

SpringCloud篇(服务拆分 / 远程调用 - 入门案例)

目录 一、服务拆分原则 二、服务拆分示例 1. 案例需求 2. 案例要求 3. 导入SQL语句 4. 实现思路 4.1. 创建父工程 cloud-demo 管理依赖 依赖导入思路 4.2. 创建子工程 order-servic 4.3. 创建子工程 user-servic 4.4. 创建 cloud_order 数据库和表并插入数据 4.5. …

特征融合篇 | YOLO11改进 | 更换上采样方式之轻量级通用上采样算子CARAFE

前言:Hello大家好,我是小哥谈。CARAFE算子的主要特点是在保持轻量级功能的同时,能够提供比其他上采样算子更好的性能。它通过少量的参数和计算量来实现高效的图像上采样。CARAFE算子能够根据像素之间的关系进行自适应的上采样,从而…

Java集合Queue——针对实习面试

目录 Java集合QueueQueue接口的特点是什么?Queue和Deque的区别?ArrayDeque和LinkedList的区别?什么是PriorityQueue?什么是BlockingQueue? Java集合Queue Queue接口的特点是什么? Queue接口在Java中是一个…