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

Days 9 函数初学

一、为什么要学函数?

刚学 C 语言的时候,所有代码全堆在main里,写重复功能要复制粘贴一大段,代码又乱又难改。函数就是用来解决这个问题的! 函数两大好处:

  1. 代码复用:同一个功能只写一次,想用直接调用,不用反复复制代码;
  2. 模块化拆分:把复杂程序拆成一个个独立小功能,逻辑清晰,找 bug、改代码都很方便。

整个 C 程序必须有且只有一个main函数,程序从main开始执行,其他都是我们自己写的自定义函数。

二、函数完整三要素:定义、调用、声明

1. 函数定义(写函数本体,实现功能)

标准语法:

拆解每一部分:

  1. 返回值类型:函数执行完给外面返回的数据类型;没有返回值写void,不用写return
  2. 函数名:命名规则和变量一样,只能字母、数字、下划线,不能数字开头,尽量见名知意,比如is_leap_year判断闰年;
  3. 形参(形式参数):函数接收外部数据的 “占位符”,只有调用函数时才会分配内存,函数结束直接销毁;
  4. 函数体{}:写具体逻辑;
  5. return:结束函数,把结果传给调用处;void函数可以省略 return。

举个简单例子:判断闰年函数

2. 函数调用(使用写好的函数)

语法:函数名(实参1, 实参2);

  • 实参(实际参数):调用时真实传进去的数据,可以是常量、变量、表达式;
  • 规则:实参的个数、顺序、数据类型必须和形参完全对应;
  • C 语言只有值传递:只是把实参的值拷贝一份给形参,函数内部修改形参,完全不会影响外面的实参。

调用上面闰年函数:

这里main主调函数is_leap_year被调函数

3. 函数声明(函数原型,解决编译报错)

C 语言代码从上往下逐行编译,如果函数定义写在 main 函数下方,编译器读到调用代码时找不到函数,直接报错。 解决办法:在 main 上方提前声明函数,告诉编译器这个函数存在。

声明格式(去掉函数体,末尾加分号):

完整带声明示例:

小总结:

  • 定义在 main 上方:不用声明;
  • 定义在 main 下方:必须提前声明。

三、变量的作用域 & 生命周期(函数配套重点)

1. 局部变量

定义在函数内部、大括号{}里的变量,就是局部变量:

  • 作用域:只能在当前大括号内使用,外面访问不到;
  • 存储位置:栈区;
  • 生命周期:进入代码块分配内存,执行完大括号直接销毁;
  • 默认存储类型auto(可以省略不写);
  • 未初始化:值是随机垃圾值,一定要手动初始化。

2. 全局变量

定义在所有函数外面的变量:

  • 作用域:整个.c文件所有函数都能访问;
  • 存储位置:静态数据区;
  • 生命周期:程序运行全程存在,程序结束才销毁;
  • 未初始化:默认自动赋值 0;
  • 缺点:所有函数都能修改,容易乱改数据,尽量少用。

四、四种变量存储类型(存储位置 / 特性)

1. auto(自动变量,局部默认)

  • 仅局部变量可用;
  • 存栈区;函数结束内存释放;
  • 不初始化 = 随机值。

2. register(寄存器变量)

  • 局部变量专用;
  • 优先存 CPU 寄存器,读取更快;寄存器满了自动降级为 auto 栈变量;
  • 不能取地址。

3. static(静态变量,分两种)

(1)static 修饰局部变量
  • 原本局部变量存栈,static 后放到静态数据区
  • 生命周期:第一次调用函数时初始化一次,之后函数调用不会重新初始化,程序结束才销毁;
  • 作用域不变:还是只能当前函数内使用;
  • 不初始化默认 0;适合计数场景。

示例:统计函数调用次数

2)static 修饰全局变量 / 函数
  • 限制作用域:只能在当前.c文件使用,其他文件无法访问,避免多文件命名冲突。

4. extern(外部声明)

只用来声明变量 / 函数,不分配内存;告诉编译器:这个变量 / 函数定义在别的文件或文件下方。

五、函数传参核心:值传递

C 语言所有函数传参都是单向值传递

  1. 调用函数时,把实参的值复制一份给形参;
  2. 实参、形参是两块独立内存,互不干扰;
  3. 在函数内部修改形参,外部实参完全不会变化。

错误示例(交换两个数字失败):

原因:只是拷贝了 a、b 的值给 x、y,函数内交换的只是副本,本体没变。

六、课堂作业实战(封装函数练习)

作业 1:封装函数,传入年月日,返回当年第几天

思路:

  1. 封装闰年判断函数is_leap_year
  2. 封装get_dayofyear(int y,int m,int d),累加前面月份总天数,加上当日;
  3. 二月天数根据闰年判断是 28/29 天。

作业 2:字符串倒置函数封装(不使用库函数)

七、新手踩坑总结

  1. 函数定义在 main 下方,忘记写函数声明,编译报错;
  2. return 返回值和函数定义的返回类型不一致,会隐式转换丢失数据;
  3. 局部变量不初始化直接使用,读取随机垃圾值;
  4. static 局部变量误以为每次调用都会重新初始化;
  5. 传参误以为修改形参能改变实参,不清楚 C 语言只有值传递;
  6. 函数名和库函数重名(比如 printf),造成程序异常;
  7. void 函数写 return 数字,语法错误。

八、学习感悟

函数是 C 语言从 “简单代码” 进阶 “模块化程序” 的分水岭,学会封装函数之后,写复杂逻辑清晰很多。尤其是 static 静态局部变量、值传递这两个点,一开始很难理解,多写几次计数、交换的练习就能吃透。后续学指针之后还能解决 “值传递无法修改外部变量” 的问题,继续加油!

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

相关文章:

  • 2026小程序制作平台哪家好:高性价比平台与工具对比
  • 2026 AI论文神器盘点,一键生成框架让你的论文思路清晰
  • Qt中实现QWidget旋转的三种方案:从paintEvent到QGraphicsView
  • SpringBoot中Logback日志框架高级配置与优化实践
  • STM32调试连接丢失问题全解析:从0x413警告到系统性排查指南
  • 「每天一芯片」LM78系列
  • 【2027最新】基于SpringBoot+Vue的Web足球青训俱乐部管理后台系统管理系统源码+MyBatis+MySQL
  • 2026年软硬件一体化的产品管理系统有哪些?选型测评与对比指南
  • 云罗GEO优化系统源码测评与性能优化解析
  • 网速测速不是统一标准!不同场景测速方式完全不一样
  • STM32 DMA技术深度解析:从核心原理到实战应用
  • Altium Designer高效操作:Ctrl/Shift键与鼠标组合的PCB设计技巧
  • JAVA德州酒吧小程序开发实战指南:从报价到流程详解
  • BaiduPCS-Go:3个颠覆性功能重塑云存储命令行体验
  • Linux命令:unalias
  • C++多态核心:虚函数表与动态绑定机制详解
  • 人类现在还有什么无法实现,预计什么时候能够实现
  • Go语言跨平台开发实战:从原理到部署
  • 如何提取偶数数组
  • 三拓化学:附着力促进剂企业,深耕广东布局华南等地区,赋能化工产业升级
  • VMWare中Ubuntu连接本地摄像头的完整指南
  • STM32备份寄存器与RTC实战:从硬件原理到低功耗应用
  • 智能工厂等级自检表:梯度培育,你的工厂在第几级?
  • 2026年7月亲测:FA工厂自动化采购平台哪家最靠谱?
  • 2026年AI内容检测工具实测与使用技巧
  • 2026 年现阶段江油专业的商场拆除回收加工厂竞争格局,谁的旧梦将在这场拆除回收里彻底碎成塑料泡沫? - 行业鉴选官
  • 2026嘉兴注册公司机构哪家靠谱?本地正规财税服务商口碑推荐 - 行业深度分析
  • GPU裸金属和GPU容器有什么区别?从隔离原理到选型一文讲清
  • 从SQL注入到容器逃逸:HackTheBox GoodGames靶机完整渗透实战解析
  • CAN总线时序与数据帧解析:从物理层信号到软件处理全流程