当前课程知识点:高级语言程序设计 >  函数 >  7.4 函数参数的传递 >  函数参数的传递

返回《高级语言程序设计》慕课在线视频课程列表

函数参数的传递在线视频

函数参数的传递

下一节:函数的嵌套调用和递归调用

返回《高级语言程序设计》慕课在线视频列表

函数参数的传递课程教案、知识点、字幕

大家好

本讲讨论主调函数和被调函数之间

是如何通过参数传递信息的

下面分4种情况讨论

函数的形参是基本类型变量

函数的形参是指针变量

函数的形参是一维数组

函数的形参是二维数组

先来看函数的形参是基本类型变量

我们想编写这样一个程序

在主函数中定义两个变量

编写子函数将主函数中这两个变量的值交换

这里我们将子函数形参定义为基本类型整型

这个任务不难

我们先定义子函数swap

形参是两个int型变量x和y

在函数体里交换了x和y的值

在main函数里

定义了两个int型变量a和b a=7 b=11

在调用这个swap函数之前

打印出这两个实参a b的值

然后调用swap函数

再调用swap函数之后

再打印输出这两个变量实参a b的值

观察一下 这两个实参的值是否进行交换

通过运行结果

发现a和b的值没有交换

那么有的人就会想

如果我们将swap函数的形参的名字改为a和b

和主函数的变量名相同

大家可以试试 会发现

主函数里变量a和b的值还是没有交换

那么基本类型的变量作为函数参数的时候

在函数调用时

无论实参和形参的名字是否相同

实参和形参在内存中

是占有不同的内存单元

主调函数只是把实参的值传递给了被调函数的形参

我们称为传值调用

形参值的变化是不会影响到实参的

如果我们希望在一个函数体内部

访问另一个函数内部的变量

是不能通过名字的

只能通过地址

也就是间接访问方式

如果希望在swap函数中

交换主函数中两个变量的值

只能将函数的形参由基本类型修改为指针类型

通过用指针类型变量作函数的形参来实现

我们将swap函数的形参

由基本类型修改为指针类型

那么在调用这个swap函数的时候

在swap函数体内部

交换的是形参指向的变量

不是两个形参之间进行交换

所以 在这两个变量前面

应该加一个间接寻址运算符*号

就表示访问这个指针变量

所指向的那个变量的内容

注意 将这个函数的形参修改为指针类型之后

我们还要将这个函数原型也做相应的修改

同时 在这个被调函数中

应该采用间接寻址的方式

来访问这两个指针变量指向的变量

在主函数里调用这个swap函数时

应该将变量a和b的地址

分别传给对应的指针类型的形参

以下两种情况能实现两数的交换吗

来看左边swap函数

第一条赋值语句

是将形参变量p1的值

也就是这个地址值 赋给temp

第二条语句

就是将形参变量p2的值赋值给p1

最后一条赋值语句

就是将temp的值赋值给形参p2

所以 在执行完这三条语句之后

我们发现形参p1和p2的值确实是互换了

但是不会影响到p1 p2指向的变量

仅仅是交换了两个形参p1 p2的值

来看右边swap函数

指针变量temp未初始化 是随机值

temp究竟指向哪一个整形变量

在这个函数当中并没有指明

指向了一个我们未知的存储单元

接下来 我们执行这条赋值语句

就是要将p1指向的那个实参变量的值

赋给temp所指向的那个存储单元

显然 这是非法的

右边swap函数

那是不能实现*p1和*p2的值互换的

也就是说我们不能借助于

一个没有初始化的指针变量

来实现两个变量的交换

现在我们再来看

用指针变量作为函数形参

还有一个好处

就是为函数提供了一种修改实参变量值的方法

如果我们需要从函数返回多个值

但用return语句

只能从被调函数返回一个值 这时

可以将函数的形参由基本类型修改为指针类型

请看任务 在主函数中定义两个变量

要求编写一个子函数

求主函数中这两个变量的和与积

要求 子函数返回值类型为void

也就是说 和与积都不能通过return 返回

先来看子函数func

我们不想让这个被调函数func

修改实参变量a和b的值

所以这里定义两个基本类型的形参x和y

用来接收main函数中传过来的a和b值

还要定义两个指针类型形参p1和p2

指针变量p1用来将a与b的和传递出去

指针变量p2用来将a与b的积传递出去

在函数func内部

将x与y的和赋给了形参p1指向的变量

将x与y的积赋给了形参p2指向的变量

我们要根据实际需要设定函数形参的数据类型

是基本类型 还是指针类型

在主函数里定义了四个变量

sum准备用来存放a与b的和

product准备用来存放a与b的积

通过调用func函数

来求出sum和product的值

通过指针我们可以在一个函数体内

访问另一个函数体的变量

这是通过变量名不能做到的

现在 我们希望定义一个函数

能对一个数组进行操作

比如说 输入这个数组所有元素的值

对这个数组所有元素进行排序

或者输出数组所有元素的值等等

定义函数时 形参是一维数组

主调函数也应该定义了一个一维数组

不能只在一方定义

主调函数的数组称为实参数组

实参数组与形参数组类型必须一致

当数组名作为函数形参时

C编译器会将形参数组名转换为指针变量

而指针变量只能接收一个地址

所以 float a 方括号中有没有数字

C编译器是忽略不计的

对形参数组的大小也不作检查

调用函数时

要将实参数组的起始地址传递给形参数组

可以这样理解

实参数组名是一个地址值

而形参数组名是被编译器解释为一个指针变量

请看实例 现在我们要编写程序

从键盘输入某班学生C语言课的成绩

这个班一共有40个人

要求分别定义三个子函数

来进行数组输入输出和求平均值

这是输入数组元素的函数InputScore

这是输出数组元素的函数OutputScore

输入输出函数没有返回值

所以函数返回值类型都为void

这是求数组平均值的函数Average

返回值类型为float

主函数中 分别调用这三个子函数

实参是数组名

后面不要方括号

数组名代表了数组的首地址

初学者通常犯这样的错误

就是在向函数传递数组的时候

在函数名的后面加上一个方括号

现在我们知道

要向这三个函数传递数组的首地址

这个原理之后

就不会犯这样的错误了

但是这三个子函数

只能对长度为40的数组进行输入输出

求平均值 怎样才能调用同一个函数

对不同长度的数组进行相同的操作

在定义子函数时

在形参表中增加一个整型变量n

用来接收主函数中实参数组实际长度

来看看改进后的代码

每个子函数定义两个形参

形参array用来接收实参数组的首地址

形参n用于接收实参数组的长度

实参score传递数组首地址

实参n传递数组长度

调用函数时

形参数组和实参数组共占用同一段内存

实参与形参的类型要一一对应

实参数组与形参数组的大小

可以一致也可以不一致

当形参被声明为一维数组时

形参列表中数组的方括号内可以为空

即使不为空 也不起作用

下面这四种书写形式是等价的

C编译器会将形参数组名转换为指针变量

对这四个函数的解读是一致的

下面来看一下

如何向函数传递二维数组

二维数组的存储方式

是和一维数组没有什么区别

但是用二维数组做参数

它的形参应该怎么写

值得注意的是

函数中的形参其实就相当于一个声明

并不产生内存分配

形参的目的就是要让编译器知道

函数参数的数据类型

向函数传递二维数组和向函数传递一维数组

都是传递这个数组的首地址

唯一不同的是向函数传递二维数组的时候

我们必须要知道二维数组的列数

也就是说 在定义函数时

如果用二维数组作形参

不能省略数组第二维的长度

这是因为我们必须知道二维数组的列数

才能从这个起始地址开始

正确的读出数组中的每一个元素

如果在形参中不说明列数

编译器将无法定位二维数组元素的位置

下面通过例5

来看看怎样定义一个函数来处理二维数组

在主函数里定义并且初始化一个二维数组

要定义一个子函数输出二维数组中所有的元素

我们分三种情况讨论

方法一 第一维的长度可以不指定

但必须指定第二维的长度

这是主函数定义的二维数组a

第一维的长度为4

第二维的长度为5

定义子函数时

形参数组第二维的数目

必须要与实参数组第二维的数目一样

在主函数中调用子函数时

第一个参数传递二维数组的首地址

第2个参数传递二维数组的行数

第3个参数传递列数 要注意

第3个参数可以小于或等于5 不能大于5

第二种方法

是将子函数的形参定义为

指向长度为5的一维数组的指针

这三种形式定义 形式是等价的

这种认识是错误的

既然一维数组作为参数相当于一个指针

那二维数组作为参数就相当于一个二级指针

如 int * *a

因为这个二级指针没有包含二维数组列的信息

第三种方法

是利用数组的顺序存储的特性

通过降维 来访问原数组

是将二维数组当一维数组来操作

a是一个一级指针

只能接收二维数组元素的地址

系统只能靠形参m和n

来划分二维数组的行数和列数

m必须小于等于5 不能大于5

在这里这种写法

是不可以写成二维数组的形式

好了本讲我们比较了下面4种情况下

函数参数的传递情况

函数的形参是基本类型变量

函数的形参是指针变量

函数的形参是一维数组

函数的形参是二维数组

谢谢大家

高级语言程序设计课程列表:

程序设计和C语言

-1.1 计算机程序和计算机语言

--计算机程序和计算机语言

--致敬先辈:伟大的C语言之父——丹尼斯·里奇 程序员

-1.2 C程序的构成

--C程序的构成

--当前主流程序设计语言各自都有什么优势?

-1.3 C语言编辑、编译、运行(VC++2010学习版)

--C语言编辑、编译、运行(VC++2010学习版)

-练习题

顺序结构程序设计

-2.1 变量的定义和使用

--变量的定义和使用

-2.2 数据类型

--数据类型简介

--整型数据

--实型数据

-2.3 格式输出和格式输入

--格式输出printf函数

--格式输入scanf函数

--单个字符的输入输出

-2.4 运算符和表达式

--运算符和表达式

-2.5 结构化程序设计入门

--结构化程序设计入门

-练习题

选择结构程序设计

-3.1 为什么要用选择结构解决问题

--为什么要用选择结构解决问题

-3.2 如何正确表示选择结构中的条件

--如何正确表示选择结构中的条件

-3.3 用if语句及if语句嵌套实现选择结构

--用if语句及if语句嵌套实现选择结构

-3.4 用switch语句实现选择结构

--用switch语句实现选择结构

-练习

循环结构程序设计

-4.1 循环的引入

-- 为什么要用循环结构解决问题

-4.1 循环的引入--作业

-4.2 用while语句实现循环

--用while语句实现循环

-4.3 用do-while语句实现循环

-- 用do-while语句实现循环

-4.4 用for语句实现循环

-- 用for语句实现循环

-4.4 用for语句实现循环--作业

-4.5 何时需要用循环的嵌套

--何时需要用循环的嵌套

-4.6 如何提前终止循环和提前结束本次循环

--如何提前终止循环和提前结束本次循环

-习题--作业

数组

-5.1 数组类型的引入

--数组类型的引入

-5.2 一维数组的定义和初始化

--一维数组的定义和初始化

-5.3 一维数组的使用

--一维数组的使用

-5.4 二维数组的定义和初始化

--二维数组的定义和初始化

-5.5 二维数组的使用

--二维数组的使用

-习题--作业

指针

-6.1 什么是指针

--什么是指针

-6.2 指针类型及相关概念

--指针类型及相关概念

-6.3 指针变量的定义、赋值与使用

--指针变量的定义、赋值与使用

-6.4 指针的运算

--指针的运算

-6.5 指针与一维数组

--指针与一维数组

-6.6 指针的指针

--指针的指针

-6.7 指针与二维数组

--指针与二维数组

-习题--作业

函数

-7.1 为什么要自定义函数

--为什么要自定义函数

-7.2 函数的定义

--函数的定义

-7.3 函数的调用

--函数的调用

-7.4 函数参数的传递

--函数参数的传递

-7.5 函数的嵌套调用和递归调用

--函数的嵌套调用和递归调用

-7.6 变量的作用域和存储类型

--变量的作用域和存储类型

-习题--作业

字符串

-8.1 字符串的存储及输入输出

--字符串的存储及输入输出

-8.2 系统字符串处理函数

--系统字符串处理函数

-8.3 自定义字符串处理函数

--自定义字符串处理函数

-习题--作业

结构体和共用体

-9.1 结构体类型的定义

--结构体类型的定义

-9.2 结构体变量及指针变量的定义及使用

--结构体类型变量和指针变量的定义和使用

-9.3 结构体变量和指针变量作函数的参数

--用结构体变量和指向结构体的指针作函数参数

-9.4 结构体数组的定义和使用

--结构体数组的定义和使用

-9.5 共用体类型和枚举类型

--共用体和枚举类型

-习题--作业

动态内存分配

-动态内存分配--习题

文件

-习题--作业

函数参数的传递笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。