【轻松学 C:编程小白的大冒险】— 16 函数的界说与调用

[复制链接]
发表于 2025-9-2 10:50:56 | 显示全部楼层 |阅读模式



  • 在编程的艺术世界里,代码和灵感须要寻找到最佳的融会点,才气打造出令人为之惊叹的作品。
  • 而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。






  • “函数在手,代码我有!”—— 来自一位成功封装了起床闹钟函数的程序员
一、函数:把代码变成“乐高积木”的魔法



  • 你有没有过如许的履历?
  • 写代码时重复写了十遍“计算圆周长”的公式,改一个参数却遗漏三个地方,末了对着报错信息抓耳挠腮?🤯
  • 别慌!编程界早就发明了“偷懒神器”——函数
  • 它就像代码世界的“乐高积木”,把重复的逻辑封装成一个个独立模块,想用的时候直接“拼”起来就行
  • 再也不用像流水线工人一样重复搬砖啦!

二、函数界说:打造你的专属“代码黑匣子”

2.1 函数的“出厂阐明书”长啥样?



  • 先来看函数的标准界说格式,一览无余👇
   

  • 翻译成人类语言就是:
  1. 返回值类型 函数名(参数1类型 参数1名称, 参数2类型 参数2名称) {
  2.     在这里写具体要执行的操作(比如计算、打印);
  3.     如果有返回值,必须用return语句把结果“吐”出来;
  4. }
复制代码


  • 特别注意:C语言规定,main函数必须是整个程序的“入口函数”,它的返回值类型必须是int。
  • 就像餐厅的大门必须有明确的“入口”标识,这是程序与操纵体系对话的“官方接口”。

2.2 三要素详解:每个零件都有大作用

① 返回值类型:函数的“快递回执”



  • int:返回整数,精准到个位,像你的年事(比如返回两数之和return a + b;)。
  • float/double:返回带小数的数,答应有误差,像体重秤的读数(比如返回圆面积return 3.14 * r * r;)。
  • void:“啥也不返”型,像发消息“已读不回”,执行完就完事(比如打印日记的函数void print_log() { ... })。
  • 特殊场景:main函数的return 0是程序向操纵体系发送的“竣工报告”,0表示“程序正常结束”,就像快递员送达后在体系里标记“签收成功”,操纵体系会根据这个数字判断程序是否顺利跑完。

② 函数名:函数的“户口本姓名”



  • 定名规则比给娃取名字还严格,必须遵守“编程界Naming公约”:
精确示范反面教材为啥不可?calc_average123_avg不能以数字开头,像“123号同砚”难记get_user_namegn太大抵!别人看不懂是干啥的check_logincheckLogin拼音+英文混搭?编程界不接受“中英混血”③ 参数列表:函数的“食材采购清单”



  • 形参(形式参数):函数界说时的“Placeholder”,相称于脚本里的角色名(比如“主角A”“配角B”),只阐明“我须要菜名和辣度”,但没说详细是啥。可以理解为函数的“临时变量”,调用时才会被赋值,就像拍戏时演员给角色赋予详细形象。
  • 实参(实际参数):调用函数时的“真材实料”,比如cook("火锅", 5),直接告诉函数“我要做5级辣的火锅”!

三、函数调用:让“代码机器人”动起来的三种姿势

3.1 直接调用:得当“干完就走”的void函数



  • 比如界说一个“打招呼”函数,直接喊它名字就行,无需接收返回值:
  1. void say_hi() {
  2.     printf("Hi, I'm your function!\n");
  3. }
  4. int main() {
  5.     say_hi(); // 直接调用,函数会打印一句话,就像喊一声“帮我打招呼”,不用等回复
  6.     return 0; // 程序跑完了,向操作系统报告“一切正常”,就像考试结束交卷时写上“考生已答完”
  7. }
复制代码

3.2 赋值调用:得当有返回值的函数



  • 把函数的返回值存到变量里,就像把外卖放进你的饭盒:
  1. int add(int a, int b) { // 加法函数,返回a+b的结果
  2.     return a + b;
  3. }
  4. int main() {
  5.     int result = add(3, 5); // 调用函数并赋值给result,相当于让函数当“计算器”,算完把结果递给你
  6.     printf("3+5=%d\n", result); // 输出8
  7.     return 0; // 带着计算结果“交差”,告诉系统“任务完成,结果正确”
  8. }
复制代码

3.3 表达式调用:让函数加入数学运算



  • 函数可以像数字一样嵌入表达式,比如边计算边乘2:
  1. int total = add(10, 20) * 2; // (10+20)*2=60,函数在这里相当于一个“会计算的数字”
复制代码

3.4 参数传递原理:值传递的“影分身魔法”



  • 想象你有一张“原图”变量original,把它传给函数beauty:
  1. void beauty(int photo) { // 形参photo是原图的“复印件”,就像你把U盘里的文件复制一份给别人,原件还在你手里
  2.     photo += 100; // 只修改复印件,原图不变,就像别人在复印件上画画,你的原件始终干净整洁
  3. }
  4. int main() {
  5.     int original = 50;
  6.     beauty(original); // 实参传递的是original的值(50),相当于把文件内容复制一份给函数
  7.     printf("原图还是%d分真实!\n", original); // 输出50,没变!因为函数拿的是“副本”,改的是“副本”
  8.     return 0; // 程序确认“原件未被修改”,安心结束
  9. }
复制代码

画个“值传递流程图”,秒懂原理👇:
   关键点:C语言默认是“值传递”,函数拿到的是参数的复印件,不会修改原始变量,就像你给朋侪的是照片复印件,原件永久在你相册里完好无损。

四、实战案例:用函数搭建“智能奶茶店体系”



  • 假设你要开辟一个奶茶店计费体系,需求如下:

  • 根据杯型(M/L/XL)计算容量
  • 根据加料(珍珠/椰果/布丁)计算代价
  • 天生订单报告
4.1 函数化拆分:把大题目拆成小零件

① 杯型转容量函数

  1. int get_cup_volume(char size) {
  2.     switch(size) {
  3.         case 'M': return 500; // 中杯500ml
  4.         case 'L': return 700; // 大杯700ml
  5.         case 'XL': return 1000; // 超大杯1000ml
  6.         default: return 0; // 防止无效输入,就像餐厅拒绝“火星杯型”的奇怪订单
  7.     }
  8. }
复制代码
② 加料计价函数

  1. float calculate_topping(int pearl, int coconut, int pudding) {
  2.     return pearl*1.5 + coconut*2.0 + pudding*3.0;
  3.     // 珍珠1.5元/份,椰果2元/份,布丁3元/份,精确计算每笔加料费用
  4. }
复制代码
4.2 主函数组装:调用函数天生订单

  1. #include <stdio.h>
  2. // 前面定义的两个函数...
  3. int main() {
  4.     // 顾客点单:大杯(L),2份珍珠,1份椰果
  5.     char cup_size = 'L';
  6.     int pearl = 2, coconut = 1, pudding = 0;
  7.    
  8.     // 调用函数计算
  9.     int volume = get_cup_volume(cup_size); // 获取容量,函数就像“杯型翻译官”,把L转成700ml
  10.     float topping_cost = calculate_topping(pearl, coconut, pudding); // 计算加料费,函数是“加料收银员”
  11.     float total_price = topping_cost + volume/100.0*5; // 基础价每100ml 5元,700ml就是7*5=35元,总价=加料费+基础价
  12.    
  13.     // 打印订单
  14.     printf("=== 您的奶茶订单 ===\n");
  15.     printf("杯型:%c杯(%dml)\n", cup_size, volume);
  16.     printf("加料:珍珠%d份,椰果%d份\n", pearl, coconut);
  17.     printf("总价:%.1f元\n", total_price);
  18.    
  19.     return 0; // 订单计算完毕,程序向系统报告“奶茶店系统已完成任务,没有bug!”,可以安心“下班”啦~
  20. }
复制代码
运行效果
  1. === 您的奶茶订单 ===
  2. 杯型:L杯(700ml)
  3. 加料:珍珠2份,椰果1份
  4. 总价:22.0元
复制代码
模块化的利益:假如未来杯型代价调解,只须要修改get_cup_volume一个函数,其他代码完全不用动,维护资本暴跌!就像奶茶店换了新的杯型模具,只须要改模具设计图,不用重装修整个店铺。
五、💡 函数利用避坑小课堂:新手必看!

5.1 返回值失落案:忘记写return

  1. int calculate(int a, int b) {
  2.     int result = a * b; // 算完了但没return!相当于做好了饭却不端上桌
  3. } // 报错:缺少返回语句,编译器大喊:“结果呢?我等着交差呢!”
复制代码
后果:函数会返回一个随机垃圾值,就像外卖没写地址,不知道会送到哪个“内存小区”,可能导致后续计算出错,就像用错误的配料做奶茶,顾客喝了要投诉!

5.2 参数类型穿越剧:实加入形参不匹配

  1. void heat_water(int temp) { // 形参是int,要求输入整数温度
  2.     printf("加热到%d度\n", temp);
  3. }
  4. heat_water(100.9); // 实参是double,强制截断为100!小数部分被“截肢”,相当于把100.9℃的水当成100℃加热
复制代码
后果:小数部门被“截肢”,实际加热温度比预期低,可能导致“奶茶不敷烫”变乱,顾客抱怨“这奶茶温吞吞的!”

5.3 函数声明失落案:先调用后界说

  1. int main() {
  2.     print_message(); // 调用在定义之前,编译器不认识!就像你没介绍朋友,直接喊“这是我兄弟”,别人会一脸懵
  3.     return 0;
  4. }
  5. void print_message() { // 定义在后面,报错!编译器说:“没提前告诉我有这个人,我不认!”
  6.     printf("Hello from function!\n");
  7. }
复制代码
解决办法:在main函数前加一句声明:void print_message();,相称于提前告诉编译器“我背面会界说这个函数,先记个名字”,就像提前告诉朋侪“等会来个叫小明的,是我哥们”。

5.4 致命错误:错误的main函数返回类型

  1. void main() { // 严重错误!C语言不允许void main,这是很多编程教材的“历史遗留问题”
  2.     printf("Hello world\n");
  3. }
  4. // ❌ 正确姿势:必须返回int
  5. int main() {
  6.     printf("Hello world\n");
  7.     return 0; // 标准结尾,缺一不可!就像写作文必须有开头和结尾,少了结尾老师要扣分
  8. }
复制代码

六、编程嘲笑话:函数的“心田OS”



  • Q:为什么函数从来不会迷路?
    A:因为它总是被“调用”(call),目的明确,不像指针喜欢随处乱指~
  • Q:为什么void函数最佛系?
    A:它没有返回值的烦恼,就像程序员遇到“需求待定”时,默默写代码不语言~
  • Q:为什么main函数的return 0像晚安问候?
    A:因为它意味着“程序本日的工作结束啦,来日诰日见~”,让操纵体系安心睡觉💤

七、✨ 今日金句

“函数是代码世界的‘瑞士军刀’,
把重复的逻辑磨成锋利的刀刃,
让你的代码像乐高一样自由拼接,
一个人就能写出千军万马的气势!”
—— 记着,return 0不是任意写的结束符,而是程序对世界的温柔告别:“我已完成任务,齐备安好。”

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

×
登录参与点评抽奖,加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表