第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课

2026-04-30
| 45页
| 59人阅读
| 0人下载
精品

内容正文:

7.4、7.5节:函数的返回值及其调用时的参数传递 C语言程序设计 电子工业出版社 理解函数返回值的概念、return语句用法及void类型 掌握值传递与地址传递的区别与联系 能够正确定义函数并使用return返回结果 能够分析并编写包含值传递和地址传递的程序 培养模块化编程思想和良好的编程习惯 增强逻辑思维能力,分析程序执行流程 知识目标 能力目标 素养目标 01 01 01 学习目标 目录 Part 01 教学导入 Part 02 知识讲授 Part 03 师生互动 Part 04 课堂练习 Part 05 课堂小结 教学导入:我们的“代码餐厅” 场景一:点餐下单 (主函数 & 调用) 你(主函数)看着菜单(函数声明),向服务员点了“宫保鸡丁”,这就是函数调用的过程。 场景二:后厨制作 (被调函数 & 参数) 后厨(被调函数)接到订单,准备鸡肉花生(处理参数),按步骤烹饪(执行函数体)。 场景三:美味上桌 (函数返回值) 香喷喷的宫保鸡丁被端上桌,这就是函数执行完成后产出的返回值。 教学导入:从“点餐”到“编程” 💡 生活中的函数映射 你的“点餐要求” 就像函数的参数,是程序运行的“输入数据” 后厨的“烹饪过程” 就像函数的函数体,是核心逻辑的“处理过程” 端上来的“美味菜肴” 就像函数的返回值,是程序最终的“输出结果” �� C语言核心概念探索 返回值的奥秘 函数如何把“烹饪好的菜肴”(计算结果)交还给我们?这是程序逻辑闭环的终点反馈。 参数传递的学问 如何将“点餐要求”(初始数据)准确无误地传递给函数?这是实现数据交互的关键桥梁。 🚀 今天,我们就来一起揭开这两个核心秘密! 知识讲授 函数的返回值及其调用时的参数传递 函数的返回值及其类型 函数调用时参数间的传递 第一部分 函数的返回值及其类型 知识讲授 知识讲授:函数的返回值 📖 核心定义 函数被调用后,执行函数体程序所取得的,并返回给主调函数的值。它是函数计算逻辑的最终输出。 传递信息的目的 将函数内部计算出的具体结果,或运行时的状态信息,回传给调用它的主程序。 唯一的传递途径 在 C 语言中,函数只能通过return 语句来将值返回给主调函数,没有其他替代方式。 主调函数 (调用方) 发起请求,等待接收数据 ➡️ 发起函数调用,传递参数 被调函数 (执行方) 执行逻辑,计算出结果数据 ⬅️ return 携带结果返回 主调函数接收并使用结果 知识讲授:return语句的两种形式 形式一:无括号写法 语法:return 表达式; 示例:return a + b; // 直接返回运算结果 注:是最常用的写法,简洁直观。 形式二:带括号写法 语法:return (表达式); 示例:return (a * b); // 括号仅改变优先级 注:功能与形式一等价,括号可选。 return 核心三大功能 1. 计算表达式的值 先对 `return` 后的表达式进行运算,得到一个具体的数值结果。 2. 回传数据给主调函数 将计算好的结果“抛出”,由调用它的上级函数接收并使用。 3. 立即终止当前函数 执行到该语句时,函数即刻停止运行,程序流程跳转回调用处。 知识讲授:函数返回值的类型 核心原则:保持一致 函数定义时声明的返回值类型,必须与 return 语句实际返回的数据类型保持严格一致,这是编写健壮代码的基础。 特殊情况:自动转换 若两者不一致,系统会以函数定义的类型为准,自动进行隐式类型转换。这虽然方便,但也隐藏着风险。 // 典型的“隐患”代码示例 int add(float x, float y) { // 定义为 int 型,但返回 float 型计算结果 return x + y; } ⚠️ 精度丢失风险 调用 add(1.5, 2.5) 时,计算结果是 4.0 (float),但会被强制转为 4 (int) 返回。小数部分被直接舍弃,导致数据失真。 最佳实践:在编写代码时,应主动确保返回值类型与函数声明完全一致,拒绝依赖隐式转换! 知识讲授:不返回值的函数——void类型 核心概念 有些函数仅执行操作(如打印信息、修改数据),不需要返回任何值。此时应将其定义为空类型(void),表示“无返回值”。 使用要点 函数体中可以省略 return 语句,程序执行到末尾会自动隐式返回;也可以使用单独的return;语句提前结束。 📝 语法定义 void 函数名(参数列表) { // 函数体:执行具体操作的代码 // 可省略 return,或使用 return; 提前退出 } 💻 代码示例 void print_hello() { printf("Hello, World! "); // 执行完自动隐式返回,无需 return 语句 } 总结:`void` 类型是函数设计中的“行动派”,专注于过程执行,不产出结果。 知识讲授:void类型的使用规范 核心红线:严禁使用返回值 一旦函数被定义为void类型,就不能在主调函数中尝试接收或使用它的返回值,这在C语言语法中是严格禁止的错误行为。 最佳实践建议 为了保证程序拥有良好的可读性并显著降低出错概率,请务必记住: “凡不要求返回值的函数,都应显式定义为 void 类型” ❌ 典型错误示范代码 void s(int n) { printf("n = %d ", n); } int main() { int sum;// 定义变量 sum = s(10);// ERROR: void函数无返回值 return 0; } 知识讲授:return 0 的概念 背诵记忆 核心机制:返回值的实现 函数返回值的核心载体是return语句,它是函数向调用者传递数据的唯一通道。 语法形式:两种标准写法 return 语句支持两种形式:return 表达式;或return (表达式);,功能完全等价。 规则约束:类型必须一致 返回值类型应与函数定义类型保持一致,若不一致,系统会尝试进行自动类型转换。 无返回值声明:void 类型 如果函数不需要返回任何数据,必须显式将其声明为void类型,这是良好的编程习惯。 重要限制:不可作为右值 声明为void类型的函数不能出现在赋值运算符的右侧,即无法将其结果赋值给变量。 💡 记忆小贴士 记住“返回”与“void”的对立关系,能帮助你快速判断函数的正确写法。 例题分析:分析以下代码的输出 程序文本 #include <stdio.h> // 函数定义为 float 类型 float calculate(int a,int b) { // 返回表达式 a / b 的值 return a/b; } main() { float res=calculate(5,2); printf("Res: %f ", res); } Q1. 函数返回值类型? 观察代码第一行函数定义,明确指定的返回类型是什么? Q2. a / b 的计算结果? 注意参数 a 和 b 均为 int 类型,整数除法的规则是什么? Q3. 最终 result 的值? 结合整数除法的结果与函数的返回类型,思考隐式类型转换的过程。 例题分析 核心逻辑拆解 类型定义:函数的返回值类型被明确声明为float浮点型。 运算规则:表达式a / b(即 5 / 2) 中,a、b 均为 int 类型,因此执行整数除法,结果为 2。 隐式转换:return 语句将 int 类型的 2 自动提升为 float 类型的2.0后返回。 运行结果验证 程序控制台输出结果: Result: 2.000000 💡 易错点提示: 在 C/C++ 中,整数间的除法会直接舍弃小数部分。如果需要得到 2.5 的结果,必须先将其中一个操作数强制转换为浮点型。 例题分析 课堂问答 Q 01 执行流程探讨 一个函数中可以有多个 return 语句吗?程序的具体执行流程是怎样的? 可以。但每次调用函数时,只会有一个 return 语句被执行。一旦执行 return,函数会立即结束运行并将结果返回给调用者。 Q 02 语法规范检查 如果一个函数定义为 int 类型,但函数体中却没有写 return 语句,程序运行时会发生什么? 这是一个语法错误。编译器通常会发出警告,程序运行时的行为是“未定义”的,极有可能返回一个不确定的随机数值。 Q 03 关键概念辨析 在C语言中,`return;` 和 `return 0;` 这两种写法有什么本质区别? return; 仅用于 void 类型的函数,表示直接结束函数。 return 0; 用于非 void 类型函数,代表函数正常结束并返回一个整数 0。 课堂练习:判断正误并说明理由 代码片段 01 void printNumber(int num) { printf("%d", num); return num; } 判断结果:错误 (×) 错误理由:函数被定义为 `void` (无返回值) 类型,因此函数体内不能出现带值的 `return` 语句。`return num;` 违反了这一规则。 代码片段 02 double getPi() { return 3.14159; } 判断结果:正确 (√) 正确理由:函数被定义为 `double` 类型,`return` 语句返回的常量 `3.14159` 属于浮点型,能够隐式转换为 `double` 类型,类型匹配合法。 课堂练习:编写函数求两数中的较大值 核心任务要求 1. 定义一个名为max的函数,功能是求两数最大值。 2. 函数需接收两个int类型的参数 x 和 y。 3. 函数执行比较逻辑,并返回较大的那个数值。 4. 在 main 函数中调用 max(15, 23),并打印最终结果。 程序文本 #include<stdio.h> int max(int x,int y) { return (x>y)?x:y; } main() { int a=15, b=23; int res=max(a,b); printf("Max:%d and %d is: %d ",a,b,res); } 课堂练习 第二部分 知识讲授 函数调用时参数间的传递 知识讲授:形参和实参 形式参数 (形参) 定义函数时,函数名后括号内的参数。它本质上是一个局部变量,仅在函数被调用时才分配内存单元。 示例:int add(int x, int y) // x, y 是形参 实际参数 (实参) 调用函数时,函数名后括号内的参数。它可以是常量、变量、表达式或函数的返回值,必须有确定的值。 示例:sum = add(3, a + b) // 3, a+b 是实参 核心机制:数据的单向传递 在函数调用发生时,系统会在内存中开辟新的空间,将实参的具体值“复制”一份,传递给对应的形参。形参的改变不会影响实参。 知识讲授:值传递的特点——“复印件”的旅行 知识讲授:值传递的特点——“复印件”的旅行 01. 数据复制 调用函数时,会将实参的值“完整复制”一份,存入形参的专属存储单元中。 02. 内存独立 形参和实参在计算机内存中占用完全不同的地址空间,是两个相互独立的变量。 03. 单向隔离 数据只能从实参流向形参。在函数内部对形参的任何修改,都不会影响主调函数中的实参。 💡 过程可视化:就像传递“复印件” 主函数(原件) 实参 a = 5 被调函数(复印件) 形参 x = 5 📝 操作:在函数内部修改形参 → x = x × 10 形参(复印件) x = 50 实参(原件) a = 5 (不变) 经典反例——交换两个数的失败 void swap(int x,int y) { int temp = x;// 交换逻辑看似正确 x = y; y = temp; printf("In swap: x=%d, y=%d", x, y); } int main() { int a=10, b=20;// 实参 swap(a, b);// ❌ 无法改变外部的 a, b return 0; } 运行结果:函数内 x,y 交换成功,但外部 a,b 的值完全未变! 💡 核心误区:值传递的“副本”特性 调用 swap(a, b) 时,系统会为形参 x, y 创建实参的“复印件”。 在函数内部,我们实际上是在交换这两张“复印件”(x, y) 的内容。而真正的“原件”(a, b) 存放在另一个房间(内存地址),完全没有被触及。 结论:修改形参 ≠ 修改实参 经典反例——交换两个数的失败 知识讲授:地址传递 值传递的局限 • 函数调用只能通过return返回一个值,无法批量输出。 • 本质是传递“复印件”,无法直接修改主调函数中的原始数据。 仅适用于简单的、无状态的 数据计算场景 实际开发的新需求 • 需要处理复杂数据结构(如数组),一次性返回或修改一批数据。 • 需要在函数内部真正交换两个数,或直接修改主调函数变量的状态。 追求更高的 程序灵活性与执行效率 核心解决方案 引入地址传递 (Address Passing)。 不再传递数据本身,而是传递数据在内存中存储的“门牌号码”。 相当于给函数一张 “藏宝图”,直接访问源头 知识讲授:地址传递的原理——传递“地址”而非“值” ▍核心概念 • 在C语言中,数组名本身就代表着数组第一个元素的地址。 • 当数组名作为函数参数时,传递的就是这个地址,而非数组的值拷贝。 ▍传递执行过程 01 调用函数时,将实参数组的首地址传递给形参数组名。 02 形参数组与实参数组在内存中指向同一块区域。 03 对形参数组的修改操作,直接作用于实参数组。 📊 原理可视化图解 实参数组 a[5] 内存首地址: 0x0010 形参数组 arr[] 接收地址: 0x0010 ⚡ 函数内部执行逻辑:arr[0] = 100;(修改首元素值) 📌 实参数组 a[5] (内存中) 同步变化: a[0] =100a[1] = 5 a[2] = 8 ... (原值不变) 结论:形参操作直接映射到实参内存空间 知识讲授:地址传递 vs 值传递 值传递 传递内容 传递实参的值(生成一份独立的副本) 内存关系 形参和实参占用完全不同的独立内存空间 数据流向 单向传递,只能由实参传递给形参 实参影响 函数内部修改形参,完全不会影响外部实参 典型应用 传递整数、浮点数等基本数据类型 地址传递 传递内容 传递实参的内存地址(指向数据的指针) 内存关系 形参和实参指向同一块物理内存空间 数据流向 双向互通,可通过地址直接操作外部数据 实参影响 函数内通过地址修改内容,会直接改变实参 典型应用 传递数组、结构体或需要被修改的变量 例题分析 程序文本【7.5】阅读下列程序,观察程序的运行结果 #include <stdio.h> void try(int x,int y,int z) { printf("(2) x=%d,y=%d,z=%d ",x,y,z); z=x+y; x=x*x; y=y*y; printf("(3) x=%d,y=%d,z=%d ",x,y,z); } main() { int a=2,b=3,c=0; printf("(1) a=%d,b=%d,c=%d ",a,b,c); try(a,b,c); printf("(4) a=%d,b=%d,c=%d ",a,b,c); } 深度思考时刻 ❓ 程序的输出结果是什么? 请在脑海中模拟程序执行流程,列出(1)至(4)四个打印语句的具体数值。 💡 为什么变量没有改变? 在调用 try( ) 函数后,main 函数中的 a, b, c 数值保持不变。这背后体现了C语言中“值传递”的什么核心机制? 例题分析 📝 执行流程拆解 main函数初始化:设定 a=2, b=3, c=0,执行首行代码打印初始状态。 02 发生值传递:调用 try() 函数时,实参值被复制给形参 (a→x, b→y, c→z),并在函数内打印此时形参。 03 函数内部操作:修改形参值 (x=4, y=9, z=5),再次打印,观察到形参已变化。 04 返回主函数:形参内存释放,main函数打印实参,值未改变。 💡 核心结论 值传递的过程,就像是传递一份“复印件”。无论你在复印件上进行任何涂写、修改或批注,都不会对原件产生任何实质性的影响。 关键发现: 实参的值在函数调用前后始终保持不变! 这完美体现了值传递「单向传递」的核心特性 例题分析 例题分析 程序文本【7.6】数组a中存放的是一名学生的5门课程的成绩,求平均成绩 #include <stdio.h> float aver(float a[], int n);//函数的声明 main() { float av; float a[5]={80,70,90,100,60};// 传递数组名(地址)和长度 av=aver(a,5); printf("average score: %f",av); } float aver(float sco[],int n) // 形参a[] 接收实参数组的首地址 { int i; float av=0; for(i=0; i<n; i++) av=av+sco[i]; av=av/5; return av; } 例题分析 01 在main函数中,定义float类型数组score并完成初始化赋值。 02 调用aver(score, 5),发生地址传递:实参 score(首地址) → 形参 a[],二者指向同一块内存。 03 遍历 a[0]~a[4] 累加求和。这实际上是在直接操作 main 函数中的 score 数组。 04 在 aver 函数内部计算平均值 av,并通过return语句将结果返回。 05 main 函数接收返回值,最终打印输出计算结果。 核心结论总结 通过地址传递机制,被调函数(如 aver)可以直接访问和操作主调函数(main)中的原始数据空间。 这在处理大量数据(如数组、结构体)时优势巨大,避免了数据的完整拷贝,极大地提高了程序的执行效率。 例题分析 课堂问答 01 值传递的“单向性” 具体指什么? 指数据只能从实参流向形参,而不能从形参流回实参。函数内部对形参的修改是局部的,不会影响到主调函数中的实参。 02 如果实参是表达式 会发生什么? 系统会先计算表达式的值(如 a+1 和 b*2),然后将计算结果作为实参的值,复制给对应的形参。这遵循了“先求值,后传递”的原则。 03 如何真正交换 main函数变量值? 仅靠值传递无法实现。我们需要使用地址传递(指针),直接操作变量的内存地址,从而在函数内部修改主调函数中的实际变量。这将是下一部分的重点内容。 课堂问答 Q1:为什么说数组名是地址? 在C语言中,数组名被设计成一个指向数组第一个元素的常量指针。它的值就是数组在内存中起始位置的地址。 Q2:地址传递是不是就没有形参和实参的区别了? 仍然有区别。实参是一个地址值(如score),形参是指针变量(如a[])。调用时,是将实参的地址值复制给了形参指针。 Q3:除了数组名,还有什么方式可以实现地址传递? 使用指针。通过`&`运算符获取变量的地址,通过`*`运算符间接访问指针指向的变量,这是更通用的地址传递方式。 背诵记忆 参数传递核心概念 •形参:函数定义时声明的局部变量,仅在函数内有效。 •实参:函数调用时传入的实际数据,传递给形参。 值传递 •核心:传递数据的“复印件”,内存空间独立。 •特点:单向传递,函数内修改形参不会影响实参。 地址传递 •核心:传递数据的“藏宝图”(内存地址),共享空间。 •特点:双向传递,函数内修改形参会直接改变实参。 关键应用与指针工具 •数组名:作为参数传递时,本质就是传递首元素地址。 •指针运算符:&取地址 *解引用(通过地址取值)。 💡 课堂金句:值传递与地址传递的根本区别在于“是否共享内存空间”。理解这一点,就掌握了C语言函数调用的核心逻辑。 课堂练习 💻 核心代码片段 #include<stdio.h> void modifyArray(int arr[],int size) { int i; for(i=0; i<size; i++) arr[i] *= 2; } main() { int nums[3] = {1, 2, 3},i; modifyArray(nums, 3); for(i=0; i<3; i++) printf("%d ", nums[i]); } 🎯 你的预测输出是? 2 4 6 🔍 核心原理解析 函数modifyArray通过地址传递接收到了数组的首地址。 在函数内部对形参的修改,会直接作用于实参nums数组的内存空间。 因此主函数输出时,数组元素已被永久修改。 课堂练习 课堂小结 课堂小结 01 / 函数的返回值 ▍核心作用 函数执行完毕后,向主调函数传递计算结果,是函数与外部环境交互的重要数据出口。 ▍关键实现 (return 语句) 使用 return 关键字将结果“带出”函数体;若函数无需返回数据,需声明为 void 类型。 ▍类型严格匹配 return 后的值类型,必须与函数定义时声明的返回值类型保持一致,否则会产生编译错误。 02 / 参数传递机制 ▍值传递 传递变量的“副本”,形参/实参独立,单向传递互不影响。 💡 比喻:给你一份文件复印件,你修改它不会影响原件。 ▍地址传递 传递变量的“内存地址”,指向同一块空间,可双向修改。 📍 比喻:告诉你文件存放的位置,你直接去修改了原文件。 ▍典型应用场景 当需要函数修改主调函数数据时使用(如:数组名作为函数参数)。 作业布置: 1.编写程序,当输入2个数a和b时,可调用自己编写的函数交换a和b的值。 2.编写函数findMaxMin,接收int数组和长度。通过地址传递,将最大值和最小值存入主函数的两个变量中。 3. 预习7.6 函数的嵌套调用和7.7 函数的递归调用。 课后任务 谢谢观看 THANKS $

资源预览图

第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课
1
第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课
2
第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课
3
第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课
4
第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课
5
第7章 第4、5节:函数的返回值及其调用时的参数传递(课件)-《C语言程序设计》(电子工业出版社)上好课
6
所属专辑
由于学科网是一个信息分享及获取的平台,不确保部分用户上传资料的 来源及知识产权归属。如您发现相关资料侵犯您的合法权益,请联系学科网,我们核实后将及时进行处理。