7.3 调用函数

前言: 

思维导图:

 7.3.1 函数调用的形式

我的笔记:

函数调用的形式
在C语言中,调用函数是一种常见的操作,主要有以下几种调用方式:

1. 函数调用语句
此时,函数调用独立存在,作为一个完整的语句。例如:

print_star();


在这种情况下,函数不需要返回值,只需完成某些操作。调用语句的末尾需要加分号。

2. 函数表达式
函数调用作为另一个表达式的一部分,例如:

c = max(a, b);


此处,`max(a, b)` 是一个函数调用,存在于赋值表达式中。在这种情况下,函数需要返回一个确定的值,以参与表达式的其他运算。例如:

c = 2 * max(a, b);

3. 函数参数
函数调用可以作为另一个函数调用的实参。例如:

m = max(a, max(b, c));


在这个例子中,`max(b, c)` 是一次函数调用,它的返回值作为第二次 `max` 函数调用的实参。

另外,函数调用可以作为其他函数,如 `printf`,的参数。例如:

printf("%d", max(a, b));

注意事项
- 调用无参函数时,括号不能省略,如 `print_star()`。
- 如果函数调用语句,末尾需要加分号;而作为表达式或参数时,不应加分号。
- 如果实参表列有多个实参,各参数间应用逗号隔开。

示例

//调用无参函数
print_star();//调用有参函数
c = max(a, b);
m = max(a, max(b, c));
printf("%d", max(a, b));

错误示范

printf("%d", max(a, b););
//这里max(a,b)后面多了一个分号,这是不正确的。

 7.3.2 函数调用时的数据传递

我的笔记:

1. 形式参数和实际参数
- **形式参数(形参)**:定义函数时,函数名后的括号中的变量。
- **实际参数(实参)**:调用函数时,函数名后的括号中的参数。

实际参数可以是常量、变量或表达式。

int max(int x, int y)
{int z;z = x > y ? x : y;return(z);
}

2. 实参和形参间的数据传递
- 实参的值会传递给形参。
- 形参获取实参的值,该值在函数调用期间有效。
- 实参与形参间的数据传递称为“虚实结合”。

示例

#include <stdio.h>int main() 
{int a, b, c;printf("please enter two integer numbers:");scanf("%d,%d", &a, &b);c = max(a, b);printf("max is %d\n", c);return 0;
}

在这个例子中,`a` 和 `b` 是实参,而 `x` 和 `y` 是形参。实参 `a` 和 `b` 的值会传递给形参 `x` 和 `y`。

注意事项
1. 实参可以是常量、变量或表达式,例如:`max(3, a+b)`。实参与形参的类型应该相同或赋值兼容。
2. 如果实参和形参类型不同,会进行类型转换。例如,如果实参是 `float` 类型,值为 `3.5`,而形参是 `int` 类型,则实参会转换为 `int` 类型,即 `3`,再传递给形参。

程序分析
1. 在定义 `max` 函数时,指定了两个 `int` 类型的形参 `x` 和 `y`。
2. 主函数中通过 `max(a, b)` 调用了 `max` 函数,其中 `a` 和 `b` 作为实参传递给了形参 `x` 和 `y`。
3. 在 `max` 函数中,将较大的值赋给变量 `z`,并作为函数值返回给主函数,赋给变量 `c`。

总结
在函数调用过程中,实参的值会传递给形参,允许在被调用函数中使用实参的值进行运算。实参和形参应当类型相同或兼容,不同类型间会进行必要的类型转换。

 

 7.3.3 函数调用的过程

 我的笔记:

1. 形参的内存分配
- 在没有函数调用发生时,定义在函数中的形参不占内存中的存储单元。
- 函数被调用时,形参才会被临时分配内存单元。

2. 实参值的传递
- 函数调用时,实参的值会被传递给对应的形参。
- 如,如果实参的值为2,那么这个值会被传递给形参x,此时,形参x的值就会变成2。

3. 形参的运算
- 形参在函数调用期间会持有值,因此我们可以利用这些形参进行相关的运算。

4. 返回值
- 通过 `return` 语句,函数值会被带回到主调函数。
- 返回值的类型应该与函数的类型一致。
- 如果函数不需要返回值,则不需要 `return` 语句,并且函数的类型应定义为 `void` 类型。

5. 调用结束后的处理
- 函数调用结束后,形参单元会被释放。
- 实参单元会被保留,并且保持原值不变。
- 如果在被调用函数的执行过程中形参的值发生了改变,这不会影响到主调函数中的实参的值。

6. 值传递
- 实参向形参的数据传递是“值传递”,是单向传递。
- 实参和形参在内存中占有不同的存储单元。
- 由于实参和形参位于不同的存储单元,实参无法获取形参的值。

总结
函数调用的过程中涉及到形参的内存分配、实参值的传递、形参的运算以及返回值的处理等多个环节。实参和形参间的数据传递是通过值传递的方式进行,即实参的值会被复制给形参,但实参和形参是独立的存储单元,它们之间的值是独立的,改变形参的值不会影响实参的值。

我的理解:

函数调用过程可以被比喻为一场精心组织的演出。在这场演出中,形参可以看作是演员,实参是演员所扮演的角色,而函数体则是演员们所要遵循的剧本。

### 1. **形参的内存分配**
   - **比喻:** 形参像是演员在剧本中的角色名称,尚未被具体的演员扮演时,它还不具有实体。
   - **解释:** 当函数被调用时,形参才会被赋予实体,即在内存中分配具体的存储单元。

### 2. **实参值的传递**
   - **比喻:** 实参是具体的演员,他们根据剧本(函数体)中角色的要求,扮演各自的角色。
   - **解释:** 在函数调用时,实参的值会被传递给形参,形参得到具体的值,以便后续的计算和操作。

### 3. **形参的运算**
   - **比喻:** 形参在演出中根据剧本的指示进行演绎,发挥着各自的角色。
   - **解释:** 形参在函数体内进行各种运算,完成函数体内定义的任务。

### 4. **返回值**
   - **比喻:** 演出完毕后,观众(主调函数)会得到一个总体的表演效果(返回值)。
   - **解释:** 函数执行完毕后,通过 `return` 语句返回一个值给主调函数。这个值应该与函数声明时的类型一致。

### 5. **调用结束后的处理**
   - **比喻:** 演出完毕后,演员退出舞台,他们扮演的角色也随之消失。
   - **解释:** 函数调用结束后,形参所占用的内存单元被释放。但是,实参依然保留其值。

### 6. **值传递**
   - **比喻:** 演员扮演角色时,他们不会改变角色原有的性格和设定,角色的设定是固定的。
   - **解释:** 实参的值会被复制给形参,但是形参和实参是两个不同的存储单元,改变形参的值不会影响到实参的值。

### 严谨科学的总结:
函数调用过程中,形参在开始时并没有内存分配,只有在函数调用时才会在内存中占有存储单元。实参的值会被复制给形参,进行函数内部的运算。运算完成后,通过 `return` 语句将结果返回给主调函数。这个过程是一种“值传递”的过程,形参和实参在内存中位于不同的存储单元,它们之间是独立的,形参的变化不会影响实参。

 7.3.4 函数的返回值(这里曾经考察过)

 我的笔记:

简述:
函数的返回值是通过`return`语句在函数中获得的。此值会带回到主调函数中。有时,返回值的类型可以自动进行类型转换,但最佳实践是让函数类型与 `return` 返回值的类型一致。

#### 笔记:

1. **返回值获取**:
   - 函数的返回值通过`return`语句在被调用函数中获得,并传递回主调函数。
   - `return`语句后的值可以是一个表达式,比如:`return(x > y ? x : y);`。

2. **返回值用途**:
   - 函数的返回值用于在主调函数中得到一个确定的值,如 `c = max(a, b);`。
   - 函数 `max(2,3)` 的返回值是 `3`,而 `max(5,3)` 的返回值是 `5`。

3. **返回值类型**:
   - 函数返回值应有明确的类型,并在定义函数时指定,如 `int max(float x, float y)`。
   - 如果 `return` 语句中的表达式类型与函数类型不一致,会按照函数类型进行转换。但最佳实践是保持一致。

4. **类型转换和清晰度**:
   - 即便可以利用类型转换在一些情况下得到不同类型的返回值,但这会降低程序的清晰度和可读性。
   - 建议初学者使函数类型与 `return` 返回值的类型保持一致。

5. **void 类型**:
   - 对于不需要返回值的函数,应定义为 `void` 类型,这会使系统确保函数不会带回任何值。
   - 在 `void` 类型的函数中,不应该出现 `return` 语句。

6. **例子分析**:
   - 当函数定义为 `int` 型,而 `return` 语句中的变量为 `float` 型时,将按赋值规则处理,先将变量的值转换为 `int` 型。
   - 例:在 max 函数中,如果变量 `z` 为 `float` 型,其值为 `2.6`,那么返回给主调函数的值将是 `2`。

7. **规范性和维护性**:
   - 应养成在定义函数时一律指定函数类型的习惯,这样的程序规范、易读、易于检查维护。

#### 举例代码:

#include <stdio.h>
int main() {int max(float x, float y);float a, b;int c;scanf("%f,%f,", &a, &b);c = max(a, b);printf("max is %d\n", c);return 0;
}int max(float x, float y) {float z;z = x > y ? x : y;return(z);
}

在这个例子中,`max` 函数比较两个 `float` 类型的值,并返回较大的一个。由于函数返回类型为 `int`,所以 `float` 类型的 `z` 在返回时会转换为 `int` 类型。

 

 

 

总结:


在学习函数调用时,要特别注意函数的定义、声明、参数传递和返回值。理解这些概念,并通过大量的实践来巩固这些知识,可以避免许多常见的错误,并且是学习更复杂编程概念的基础。同时,要特别注意类型的一致性和变量的作用域,确保在编写程序时不会出现相关的错误。

调用函数 - 重点、难度与易错点

#### 重点:
1. **函数定义与声明**:
   函数的定义包含了具体的实现,而声明通常出现在头文件中,通知编译器函数的存在。

2. **参数传递**:
   理解参数是如何传递的,包括值传递和引用传递,这是实现更复杂逻辑时的基础。

3. **返回值**:
   函数可以返回一个值,通过 `return` 语句来实现。必须清楚函数的返回类型,并使 `return` 语句与之匹配。

4. **作用域**:
   理解变量的作用域,局部变量与全局变量的区别和使用场景。

5. **调用过程**:
   了解函数被调用时的执行流程,以及调用者和被调用者之间是如何交互的。

#### 难度:
1. **参数传递理解**:
   新手可能会对值传递和引用传递感到困惑,不清楚变量在函数间是如何传递和修改的。

2. **递归调用**:
   如果本节包含递归调用,那么理解递归调用的执行过程和调用栈可能会有些难度。

3. **类型一致性**:
   保持函数定义类型、`return` 语句和调用处类型的一致性,可能需要一些时间来掌握。

#### 易错点:
1. **类型不一致**:
   函数的返回值类型与 `return` 语句不匹配,或与接收返回值的变量类型不匹配,是一个常见的错误。

2. **遗漏返回值**:
   忘记在需要返回值的函数中加 `return` 语句,或在 `void` 类型的函数中加了 `return` 语句。

3. **参数传递错误**:
   错误地使用值传递或引用传递,导致函数内外的变量未按预期改变。

4. **作用域混淆**:
   对全局变量和局部变量的作用域不清晰,可能导致变量的错误使用。

5. **递归终止条件缺失**:
   如果涉及递归,缺少或错误的递归终止条件会导致程序运行错误

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

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

相关文章

ARINC825规范简介

ARINC825规范简介 机载CAN网络通用标准 ARINC825规范全称为机载CAN网络通用标准&#xff08;The General Standardization of CAN for Airborne Use&#xff09;。顾名思义&#xff0c;ARINC825规范是建立在CAN物理网络基础上的高层规范。CAN网络使用共享的双绞电缆传输数据&…

接雨水问题

接雨水问题 问题背景 LeetCode 42. 接雨水 接雨水问题是一个经典的计算雨水滞留量的问题&#xff0c;通常使用柱状图来表示不同高度的柱子。在下雨的情况下&#xff0c;柱子之间的凹陷部分能够存储雨水&#xff0c;问题的目标是计算这些柱子所能接收的雨水总量。 相关知识 …

【人工智能导论】线性回归模型

一、线性回归模型概述 线性回归是利用函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。简单来说&#xff0c;就是试图找到自变量与因变量之间的关系。 二、线性回归案例&#xff1a;房价预测 1、案例分析 问题&#xff1a;现在要预测140平方的房屋的价格&…

【HUAWEI】单臂路由

目录 ​ &#x1f96e;写在前面 &#x1f96e;2.1、拓扑图 &#x1f96e;2.2、操作思路 &#x1f96e;2.3、配置操作 &#x1f363;2.3.1、LSW4配置 &#x1f363;2.3.2、R2配置 &#x1f363;2.3.3、测试网络 &#x1f990;博客主页&#xff1a;大虾好吃吗的博客 &…

求∑(1,n)⌊k/i⌋∗i

对于[k/i]*i,我们可以分两端&#xff0c;前,最多有段&#xff0c;后边从到n&#xff0c;取值范围为1-&#xff0c;所以最多有段&#xff0c;共2*段。对于每段从i开始&#xff0c;其上界jk/(k/i)&#xff08;维持k/i不变最大范围i-j&#xff09;。 计算[k/i]*i时间复杂度降到级…

十大常见排序算法详解(附Java代码实现和代码解析)

文章目录 十大排序算法⛅前言&#x1f331;1、排序概述&#x1f334;2、排序的实现&#x1f335;2.1 插入排序&#x1f433;2.1.1 直接插入排序算法介绍算法实现 &#x1f433;2.1.2 希尔排序算法介绍算法实现 &#x1f335;2.2 选择排序&#x1f433;2.2.1 选择排序算法介绍算…

在linux下预览markdown的方法,转换成html和pdf

背景 markdown是一种便于编写和版本控制的格式&#xff0c;但却不便于预览——特别是包含表格等复杂内容时&#xff0c;单纯的语法高亮是远远不够的——这样就不能边预览边调整内容&#xff0c;需要找到一种预览方法。 思路 linux下有个工具&#xff0c;叫pandoc&#xff0c…

华为云云耀云服务器L实例评测 | 实例使用教学之简单使用:通过部署宝塔面板可视化管理华为云云耀云服务器

华为云云耀云服务器L实例评测 &#xff5c; 实例使用教学之简单使用&#xff1a;通过部署宝塔面板可视化管理华为云云耀云服务器 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为…

【C语言经典100例题-66】(用指针解决)输入3个数a,b,c,按大小顺序输出。

代码&#xff1a; #include<stdio.h> #define _CRT_SECURE_NO_WARNINGS 1//VS编译器使用scanf函数时会报错&#xff0c;所以添加宏定义 swap(p1, p2) int* p1, * p2; {int p;p *p1;*p1 *p2;*p2 p; } int main() {int n1, n2, n3;int* pointer1, * pointer2, * point…

ARM---实现1-100求和任务

.text .globl _start_start:mov r0, #0x1mov r1, #0x1 给r1加一固定1不变mov r2, #0x64 100判断bl sumcmp r1, r2 sum:addcc r1, r1,#0x1 r1自增addcc r0, r0, r1 r0求和movcc pc,lrstop:b stop.end

BI神器Power Query(27)-- 使用PQ实现表格多列转换(3/3)

实例需求&#xff1a;原始表格包含多列属性数据,现在需要将不同属性分列展示在不同的行中&#xff0c;att1、att3、att5为一组&#xff0c;att2、att3、att6为另一组&#xff0c;数据如下所示。 更新表格数据 原始数据表&#xff1a; Col1Col2Att1Att2Att3Att4Att5Att6AAADD…

Hive【Hive(三)查询语句】

前言 今天是中秋节&#xff0c;早上七点就醒了&#xff0c;干啥呢&#xff0c;大一开学后空教室紧缺&#xff0c;还不趁着假期来学校等啥呢。顺便偷偷许个愿吧&#xff0c;希望在明年的这个时候&#xff0c;秋招不知道赶不赶得上&#xff0c;我希望拿几个国奖&#xff0c;蓝桥杯…

火热报名中 | 2天峰会、20+热门议题,AutoESG 2023数智低碳---中国汽车碳管理创新峰会亮点抢先看!

在碳中和的背景下&#xff0c;减碳之风吹遍全球&#xff0c;而汽车行业则由于产业链长、辐射面广、碳排放总量增长快、单车碳强度高的特点&#xff0c;成为各国碳排放管理的监管重点&#xff0c;聚焦汽车业的碳博弈也逐步升级。 2020年&#xff0c;国务院办公厅印发的《新能源…

douyin 六神x-helios / x-medusa解密记录学习

在某音新版本的抓包中&#xff0c;经常会遇到两个熟悉的字段x-helios &#xff0c;x-medusa&#xff0c;它是新版本中风控的重要组成部分。 通常而言&#xff0c;我们可以使用像frida&#xff0c;unidbg来模拟计算出六神参数&#xff0c;比如说我们随便找一个23.9版本生成一个…

K折交叉验证——cross_val_score函数使用说明

在机器学习中&#xff0c;许多算法中多个超参数&#xff0c;超参数的取值不同会导致结果差异很大&#xff0c;如何确定最优的超参数&#xff1f;此时就需要进行交叉验证的方法&#xff0c;sklearn给我们提供了相应的cross_val_score函数&#xff0c;可对数据集进行交叉验证划分…

【深度学习实验】卷积神经网络(六):自定义卷积神经网络模型(VGG)实现图片多分类任务

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. 构建数据集&#xff08;CIFAR10Dataset&#xff09; a. read_csv_labels&#xff08;&#xff09; b. CIFAR10Dataset 2. 构建模型&#xff08;FeedForward&…

Unity:2D游戏设置相机orthographicSize

目录 根据设备分辨率动态设置相机 orthographicSize 根据设备分辨率动态设置相机 orthographicSize 2d游戏里面相机的Orthan.size确定的是高度&#xff0c;宽度是按照屏幕的宽高比计算出来的cameraWidthSize camera.Orthographic.size*(Screen.Width/Screen.height)我在游戏…

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③ 第十八章 Linux系统对中断的处理 ③18.5 编写使用中断的按键驱动程序 ③18.5.1 编程思路18.5.1.1 设备树相关18.5.1.2 驱动代码相关 18.5.2 先编写驱动程序18.5.2.1 从设备树获得 GPIO18.5.2.2 从 GPIO获得中断号18.5…

【JVM】第三篇 JVM对象创建与内存分配机制深度剖析

目录 一. JVM对象创建过程详解1. 类加载检查2. 分配内存2.1 如何划分内存?2.2 并发问题3. 初始化4. 设置对象头5. 执行<init>方法二. 对象头和指针压缩详解三. JVM对象内存分配详解四.逃逸分析 & 栈上分配 & 标量替换详解1. 逃逸分析 & 栈上分配2. 标量替换…

查看react内置webpack版本的方法

yarn list --pattern webpack npm ls --pattern webpack