当前位置: 首页 > news >正文

C语言:函数

C语言:函数

  • 一.函数概念
  • 二.库函数
    • 1.什么是库函数
    • 2.如何使用库函数
    • 3.库函数文档的一般格式(以rand函数为例)
  • 三.自定义函数
  • 四.形参和实参
  • 五.return语句的详细使用
  • 六.数组做函数参数
  • 七.函数的嵌套调用和链式访问
    • 1.嵌套调用
    • 2.链式访问
  • 八.函数的声明和定义
    • 1.为什么要函数声明
    • 2.多个文件时
  • 九.关键字static和extern
    • 1.static介绍
      • static修饰局部变量
      • static修饰全局变量
      • static修饰函数
    • 2.extern

一.函数概念

在 C 语言中,函数是实现特定功能、相对独立的代码模块,也是程序的基本组成单位。它由函数名、参数列表、函数体等部分构成,可以接收外部传入的数据,执行相应的处理逻辑,并可返回处理结果。函数具有可重复调用的特点,能够将复杂程序拆分为多个功能单一的模块,既避免代码重复编写,也让程序结构更清晰、易于维护和扩展,而程序的执行则从main函数开始。

一般分为两类函数:库函数和自定义函数。

二.库函数

1.什么是库函数

直白的说,库函数 = 别人已经写好、封装好、你直接拿来用的函数

  1. 编程语言自带一批常用功能(比如输入输出、数学计算、字符串处理)
  2. 这些功能被打包成 “函数库”
  3. 你写程序时,直接调用里面的函数,不用自己重新写一遍逻辑

例如:
想要打印一句话,要用printf
想要输入,要用scanf
想算平方根,要用sqrt等等。
这些都不是你自己写的,而是语言自带的库函数

总结:不用自己写,直接调用的现成函数,就是库函数

2.如何使用库函数

库函数是在标准库中对应的头文件中声明的,所以库函数的使用要包含对应的头文件。

相关学习工具:
库函数相关头文件

举个例子:
在此之前我们学过rand函数,在使用rand函数时要包含头文件#include <stdlib.h>

#include<stdio.h>#include<stdlib.h>intmain(){printf("%d\n",rand());printf("%d\n",rand());printf("%d\n",rand());return0;}

运行结果:

3.库函数文档的一般格式(以rand函数为例)

1函数原型

2.函数功能介绍

3.参数和返回类型说明

4.代码举例

5.代码输出

6相关知识链接

三.自定义函数

自定义函数无非就是自己写代码创造出来的函数,不包含在库函数里。

例如:

#include<stdio.h>ret_typefun_name(形式参数)//ret_type-->函数返回类型{//函数体}intmain(){fun_name(形式参数);//函数名return0;}

注意:如果ret_type不知道返回什么,可使用void,明确表示函数没有参数;如果有参数,要交代清楚参数的类型和名字,以及参数个数。

举个例子:输入2个整型类型的参数,函数计算的结果也是整型

#include<stdio.h>intAdd(intx,inty){returnx+y;}intmain(){inta=0;intb=0;scanf("%d %d",&a,&b);intr=Add(a,b);printf("%d\n",r);return0;}

四.形参和实参

实参:真实传递给函数的参数。
形参:只是形式上存在的,不会向内存申请空间,不会真实存在的,如上述代码中的int x, int y所以叫形式参数。

在上述代码中我们可以看到在main函数中int r = Add(a, b);从scanf接收a和b,这是实参;而函数Add自己创建了int x, int y,这是形参。形参中的x和y也可以用a和b来代替,于实参字母相同,最终效果都是一样的。

如图所示:

#include<stdio.h>intAdd(inta,intb){returna+b;}intmain(){inta=0;intb=0;scanf("%d %d",&a,&b);intr=Add(a,b);printf("%d\n",r);return0;}

实参与形参之间的关系:在VS里调试时x和y确实得到了a和b的值,但是x和y的地址和a和b的地址是不⼀样的,所以我们可以理解为形参是实参的⼀份临时拷贝

五.return语句的详细使用

  1. return后边可以是⼀个数值,也可以是⼀个表达式,如果是表达式则先执行表达式,再返回表达式
    的结果。
  2. return后边也可以什么都没有,直接写return; 这种写法适合函数返回类型是void的情况。
    return语句执行后,函数就彻底返回,后边的代码不再执行。
  3. return返回的值和函数返回类型不⼀致,系统会自动将返回的值隐式转换为函数的返回类型。
  4. 如果函数中存在if等分支的语句,则要保证每种情况下都有return返回,否则会出现编译错误。
  5. 函数的返回类型如果不写,编译器会默认函数的返回类型是int
  6. 函数写了返回类型,但是函数中没有使用return返回值,那么函数的返回值是未知的。

六.数组做函数参数

有时我们在写代码时难免会用到,例如后续我们结合本章和之前所学的知识写一个简单的扫雷游戏中,就要用到数组做函数参数。

举个例子:写⼀个函数将⼀个整型数组的内容,全部置为-1,再写⼀个函数打印数组的内容

参考代码:

#include<stdio.h>voidset_arr(intarr[],intsz){inti=0;for(i=0;i<sz;i++){arr[i]=-1;}}voidprint_arr(intarr[],intsz){inti=0;for(i=0;i<sz;i++){printf("%d ",arr[i]);}printf("\n");}intmain(){intarr[]={1,2,3,4,5,6,7,8,9,10};intsz=sizeof(arr)/sizeof(arr[0]);//计算数组元素个数set_arr(arr,sz);//设置数组内容为-1print_arr(arr,sz);//打印数组内容return0;}

七.函数的嵌套调用和链式访问

1.嵌套调用

嵌套调⽤就是函数之间的互相调⽤。

大概结构框架:

#include<stdio.h>ret_typefun_name2(形式参数){//函数体}ret_typefun_name1(形式参数){fun_name2(形式参数);}intmain(){fun_name1(形式参数);return0;}

2.链式访问

链式访问就是将⼀个函数的返回值作为另外⼀个函数的参数。

举一个简单的例子:求⼀个字符串的长度
我们一般会这样写:

#include<stdio.h>intmain(){intlen=strlen("abcdef");printf("%d\n",len);return0;}

如果再加以改进,就会变为链式访问结构,如代码所示:

#include<stdio.h>intmain(){printf("%d\n",strlen("abcdef"));return0;}

这便是链式访问

八.函数的声明和定义

1.为什么要函数声明

我们先来看这种代码写法,一般最后运行结果是不会出错的

#include<stdio.h>ret_typefun_name1(形式参数){}intmain(){fun_name1(形式参数);return0;}

我们再来看看这种代码写法,我们去调试会报错,这是因为程序是自上而下运行的,但走到fun_name1(形式参数)时,在前面编译器没有遇到过ret_type fun_name1(形式参数),结果就会报错

#include<stdio.h>intmain(){fun_name1(形式参数);return0;}ret_typefun_name1(形式参数){}

那我们又该如何解决呢?这就得在main函数前使用函数声明

#include<stdio.h>ret_typefun_name1(形式参数)intmain(){fun_name1(形式参数);return0;}ret_typefun_name1(形式参数){}

再次调试程序,结果成功了

总结

  1. 函数的调用⼀定要满足,先声明后使用;
  2. 函数的定义也是⼀种特殊的声明,所以如果函数定义放在调用之前也是可以的。

2.多个文件时

上述情况是在单个文件的情况下,但我们写代码不可能把所有代码都放在一个文件里面吧,所有可以把代码拆分放在多个文件中。

⼀般情况下,函数的声明、类型的声明放在头文件后缀为.h中,函数的实现是放在源文件后缀为.c文件中。

操作方法:>>
右击源文件,添加,新建项,然后有两个选项,一个是.c后缀的c++文件,另一个是.h后缀的头文件。

如图所示:


其中
game.h为函数声明

game.c为函数的定义

test.c为程序逻辑,即main函数所在文件

九.关键字static和extern

1.static介绍

static静态的意思,其作用:

  1. 修饰局部变量
  2. 修饰全局变量
  3. 修饰函数

static修饰局部变量

static 局部变量相当于只会初始化一次、能记住上次值的 “长寿局部变量”,延长了程序生命周期。

我们将普通的局部变量与static修饰过后的局部变量进行对比

普通的局部变量
1.函数一调用就创建,函数一结束就销毁,下次调用重新开始。

static修饰的局部变量
1.只在第一次调用时创建,之后一直活着,不会消失。
2.下次再调用这个函数,它会记住上一次的值,不会重置。

例如:

voidtest(){staticinta=0;a++;printf("%d ",a);//第一次调用test()时,a=1//第二次调用test()时,a=2//第三次调用test()时,a=3......}

static修饰全局变量

static修饰全局变量,就是把这个变量 “锁在当前文件里”,不让别的文件访问。

我们将正常的局部变量与static修饰过后的全局变量进行对比

正常全局变量
1.整个项目所有.c文件都能访问、修改
2.很容易被别的文件不小心改掉,不安全
static修饰的全局变量
1.只能在当前这个.c文件里用
2.别的文件看不见、用不了、改不了
3.相当于给变量加了个本文件专属的限制

static修饰函数

简单的来说,普通函数时整个项目里所有文件都能调用的,而我们static修饰后的函数相当于这个函数只给自己所在的 .c 文件用,别的文件调用不了

例如我们在上面的game.c文件里某个函数前面加上一个static来修饰,那么我们的test.c文件对应的函数想调用是不可能的

如下所示:

2.extern

extern是用来声明外部符号。
如果⼀个全局的符号在A文件中定义的,在B文件中想使⽤,就可以使用extern进行声明,然后使用。

如下所示:


然后我们开始调用,最后成功打印100;那如果我们在int hhh = 100;前面加上static后,还会成功打印100吗?

结果是不会的,因为我们在此之前已经明确说明了当static修饰全局变量,就是把这个变量 “锁在当前文件里”,不让别的文件访问。

http://www.jsqmd.com/news/610712/

相关文章:

  • 2026年热门测量显微镜品牌厂家推荐:工业质检选购避坑指南
  • 别再单机跑ETL了!手把手教你用Kettle 9.2.0搭建跨平台(Win+Linux)集群,处理海量数据
  • 为什么92%的Mojo开发者卡在插件安装环节?深度解析conda/pip/mojopm三工具兼容性冲突与降级方案
  • 再次革新 .NET 的构建和发布方式(一)日
  • 手把手教你用C#和VISA库控制Keysight 34461A万用表(VS2022环境)
  • 拆穿名词诈骗!用大白话理解晦涩难懂的AI概念媳
  • 【声纳与人工智能融合——从理论前沿到自主系统实战(进阶篇)】第十七章 声学情报(ACINT)的大语言模型(LLM)增强解析
  • 工业双氧水的危害及注意事项
  • OpenClaw技能扩展:安装Qwen3.5-9B专用代码审查模块
  • DejaVuSansMono嵌入式位图字体库深度解析
  • 为 Go 语言中的 sync.WaitGroup 添加超时等待机制
  • SAP MM模块预留功能实战:从创建到发料的完整流程解析
  • 再次革新 .NET 的构建和发布方式(一)窘
  • 别再手动折腾了!用Docker在Linux上5分钟搞定Terraria TShock服务器(含国内镜像加速)
  • 百川2-13B-4bits量化模型+OpenClaw:法律文书审查助手个人版
  • 第十六届蓝桥杯国赛题客观题解析及知识点
  • 基于Python的IT行业岗位数据分析与可视化
  • 你的JS代码总在半夜崩溃?TypeScript来“上保险”了
  • OpenClaw跨平台控制:Qwen3-14B管理多台设备的自动化流
  • mysql如何审计误删除数据操作_mysql binlog逆向分析追踪
  • 理查森外推法详解:从数学原理到Python实现(保姆级教程)
  • 【声纳与人工智能融合——从理论前沿到自主系统实战(进阶篇)】第十八章 海底底质智能反演的多分支物理先验网络
  • 进口两级压缩技术赋能工业节能:昆西的全球化实践与洞察
  • 【教学类-160-01】20260408 AI视频培训-练习1“豆包AI视频”
  • Obsidian 零基础入门教程
  • AUTOSAR兼容性验证失败?车载C#中控系统代码合规性自查清单,含ISO 26262 ASIL-B级代码审计模板
  • 为什么你的.NET 9容器镜像比别人胖47%?——官方SDK分层优化与多阶段构建深度拆解(实测数据支撑)
  • 手把手教你用Cherry Studio+蓝耘API,5分钟把Qwen3-VL-32B变成你的私人图表分析助手
  • 数字信号完整性分析:眼图原理与应用详解
  • 从安装到验证:一步步教你如何在Ubuntu上使用apt-get安装gfortran-6