C语言第9章 函数_第1页
C语言第9章 函数_第2页
C语言第9章 函数_第3页
C语言第9章 函数_第4页
C语言第9章 函数_第5页
已阅读5页,还剩87页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第九章函数本章学习内容本章首先总括的说明了C语言的函数与程序结构。然后介绍了函数的定义、函数的参数、函数的返回值、函数的调用、函数的嵌套调用和函数的递归调用。还介绍了数组作为函数的参数。介绍了局部变量与全局变量以及变量的存储类别。通过一个具体的多源文件程序的例子说明了工程文件的创建和生成可执行文件的方法。最后介绍了编译预处理的有关知识。本章学习目的

掌握函数的定义和调用方法,使学生进一步掌握结构化程序设计的方法。了解形式参数、实际参数、传值和传地址的基本概念。能设计具有自定义函数的程序,包括函数的嵌套调用以及函数的递归调用的程序。掌握变量的作用域和变量的生存期,掌握编译预处理的有关知识。

本章学习重点和难点重点:1.函数的定义。2.主调函数与被调函数之间参数的传递。难点:函数的递归调用。第九章函数9.1概述9.2

函数定义的一般形式9.3函数参数和函数的值9.4

函数的调用9.5

函数的嵌套调用9.6

函数的递归调用9.7数组作为函数的参数9.8局部变量和全局变量9.9变量的的存储类别9.10工程文件9.11

编译预处理9.1概述一个C程序可由一个主函数和若干个函数构成。由主函数调用其他函数,其他函数也可以互相调用。同一个函数可以被一个或多个函数调用任意多次。

9.1概述

在程序设计中,常常将一些常用的功能模块编写成函数,放在函数库中供选用。从而减少程序段的重复编写。

9.1概述例1函数printstar()的功能为打印一行*号,函数print_message()的功能为打印HappyNewYear!,按下列格式在屏幕上输出:**********************

HappyNewYear!**********************9.1概述说明:(1)一个源程序文件由一个或多个函数组成。一个源程序文件是一个编译单位,即以源程序为单位进行编译,而不是以函数为单位进行编译。

(2)一个C程序由一个或多个源程序文件组成。对于较大的程序,一般不希望全部放在一个文件中,而将函数和其他内容分别放在若干个源文件中,再由若干个源文件组成一个C程序。这样可以分别编写、分别编译,提高工作效率。一个源文件可以为多个C程序公用。9.1概述(3)C程序的执行从main函数开始,条用其他函数后流程返回到main函数,在main函数中结束整个程序的运行。main函数是系统定义的。

(4)所有函数都是平行的,即在定义函数时是互相独立的,一个函数名不从属另一函数,即函数不能嵌套定义。函数间可以互相调用,但是不能调用main函数。

9.1概述(5)从用户使用的角度看,函数可分为两类:①标准函数,即库函数。这是由系统定义的,用户可以直接使用,但在使用前要将相应的头文件包含到程序中去。②用户自己定义的函数。用以解决用户专门的需要。

9.1概述(6)从函数的形式看,函数可分为两类:①无参函数。例1中的printstar和print_message函数就是无参函数。②有参函数。在调用函数时,在主调函数和被调函数之间有数据的传递。也就是说,主调函数可以将数据传给被调函数使用,被调用函数中的数据也可以带回来供主调函数使用。9.2

函数定义的一般形式1.无参函数的定义形式类型标识符

函数名(){声明部分

语句}

例1中的printstar和print_message函数就是无参函数。

9.2

函数定义的一般形式2.有参函数定义的一般形式类型标识符

函数名(形式参数列表){声明部分

语句}

9.2

函数定义的一般形式3.可以有“空函数”形式:类型标识符

函数名(){}例如:dummy(){}

9.2

函数定义的一般形式例1求出2个任意整数中的最大数,并输出。/*求两个任意整数中的最大值*//*现代形式参数说明方式*/main(){inta,b,c;printf("请输入a,b:");scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis:%d\n",c);}intmax(intx,inty)/*定义有参函数max*/{intz;/*函数中的说明部分*/

z=x>y?x:y;return(z);}

9.2

函数定义的一般形式

例2编写学生成绩管理系统菜单程序。

9.2

函数定义的一般形式

4.对形参声明的传统方式/*求两个任意整数中的最大值*//*传统形式参数说明方式*/main(){inta,b,c;printf("请输入a,b:");scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis:%d\n",c);}

intmax(x,y)/*指定参数x,y*/intx,y;/*对参数进行类型说明*/{intz;z=x>y?x:y;return(z);}9.2

函数定义的一般形式

一般把这种方法称为传统的对形式参数的声明方式,而把前面介绍的方法称为现代的方式。TurboC和目前使用的多数C版本对这两种方法都允许使用,两种方法等价,ANSI新标准推荐前一种方法即现代方式。9.3函数参数和函数的值9.3.1

形式参数和实际参数9.3.2

函数的返回值

9.3.1形式参数和实际参数形式参数——在定义函数时函数名后面圆括弧中的变量名称为形式参数,简称为形参。实际参数——在主调函数中调用一个函数时,函数名后面圆括弧中的参数称为实际参数,简称为实参。9.3.1形式参数和实际参数例1

调用函数时的数据传递。9.3.1形式参数和实际参数

关于形参和实参的说明:

(1)在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。只有在发生函数调用时,函数中的形参才由系统分配内存单元。在调用结束后,形参所占的内存单元也被释放。9.3.1形式参数和实际参数

(2)实参可以是常量、变量或表达式。但要求它们有确定的值,在调用时将实参的值赋给形参(如果是数组名,则传递的是数组首地址而不是数组的值)。例如:max(3,a+b);9.3.1形式参数和实际参数

(3)在被定义的函数中,必须指定形参的类型。9.3.1形式参数和实际参数

(4)实际参数与实际参数的类型应性同或赋值兼容。如果实际参数为整型而形式参数为实型,或者相反,则按照前面介绍的不同类型数据的赋值规则进行转换。例如,实际参数值a为3.5,而形式参数x为整型,则将实数3.5转换成整型数3,然后送到形式参数b。但此时应将max函数放在main函数的前面或在main函数中对被调用函数max作原型声明,否则会出错。9.3.1形式参数和实际参数

(5)C语言规定,实参变量对形参变量的数据传递是“值传递”,即单向传递,只由实参传给形参,而不能由形参传回来给实参。9.3.1形式参数和实际参数例2交换两个变量的值。注意:C语言中,由于参数传递是单向的,所以这是一个错误的程序。

9.3.1形式参数和实际参数

例3分析下列程序。main(){intx=2,y=3,z=0;printf("*x=%d,y=%d,z=%d\n",x,y,z);try(x,y,z);/*函数调用,x,y,z为实参*/

printf("****x=%d,y=%d,z=%d\n",x,y,z);}

try(intx,inty,intz){printf("**x=%d,y=%d,z=%d\n",x,y,z);

z=x+y;x=x*x;y=y*y;printf("***x=%d,y=%d,z=%d\n",x,y,z);}9.3.2

函数的返回值说明:(1)函数的返回值是通过函数中的return语句获得的。return语句将被调用函数中的一个确定值带回主调函数中去。9.3.2

函数的返回值

例4已知x,求y的值。

2x2-xx≥0y=2x2x<09.3.2

函数的返回值(2)函数值的类型。既然函数有返回值,这个值当然应属于某一个确定的类型,应当在定义函数时指定函数值的类型。例如:

intmax(intx,inty)

C语言规定,凡不加类型说明的函数,一律自动按整型处理。9.3.2

函数的返回值(3)如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型。9.3.2

函数的返回值(4)如果被调用函数中没有return语句,并不带回一个切顶的、用户所希望得到的函数值,但实际上,函数并不是不带回值,而只是不带回有用的值,带回的是一个不确定的值。

(5)为了明确表示“不带回值”,可以用“void”定义无类型(或称为空类型)。9.3.2

函数的返回值例6将前面打印程序中的printstar()和print_message()函数定义成为无类型函数。

9.4

函数的调用9.4.1

函数调用的一般形式9.4.2

函数调用的方式9.4.3对被调用函数的声明和函数原型9.4.1

函数调用的一般形式函数调用的一般形式:

函数名(<实际参数列表>);

9.4.1

函数调用的一般形式说明:(1)如果是调用无参函数,则<实际参数列表>可以省略,但是括号不能省。(2)如果实际参数列表中包括多个实际参数,则个参数之间用逗号隔开。(3)实际参数与形式参数的个数应相等,类型应一致。实际参数与形式参数按顺序对应,一一传递。

9.4.1

函数调用的一般形式(4)如果实际参数列表中包括多个参数,对实际参数求值的顺序接顶于编译系统。有的系统按自左至右,有的系统则按自右至左的顺序。例如TurboC和MSC是按自右至左的顺序求值的。9.4.2

函数调用的方式1.函数语句main(){printstar();/*调用printstar函数*/

print_message();/*调用print_message函数*/

printstar();/*调用printstar函数*/}9.4.2

函数调用的方式

2.函数表达式函数出现在一个表达式中,这种表达式称为函数表达式。这时要求函数带回一个确定的函数值参加表达式的运算。例如:

c=2*max(a,b);9.4.2

函数调用的方式3.函数参数函数调用作为一个函数的参数。例如:printf(“%d”,max(a,b));

9.4.3对被调用函数的声明和函数原型被调用函数应具备的条件:(1)被调用函数必须似乎已经存在的函数,可以是库函数或用户自定义函数。(2)如果使用库函数,必须在文件开头使用#include命令将调用有关库函数的所有需要的信息包含到本文件中来。9.4.3对被调用函数的声明和函数原型(3)如果使用用户自定义函数,而且该函数与调用它的函数在用一个文件中,一般还应在主调用函数中对被调用的函数作声明。

声明——向编译系统声明将要调用的函数,并将有关信息通知编译系统。

9.4.3对被调用函数的声明和函数原型

以上函数声明称为——函数原型。使用函数原型的作用主要是利用它在程序的编译阶段对函数的合法性做全面的检查。9.4.3对被调用函数的声明和函数原型函数原型的一般形式:形式1:

函数类型函数名(<参数类型1>,<参数类型2>,…);形式2:函数类型函数名(<参数类型1参数名1>,<参数类型2参数名2>,…);

9.4.3对被调用函数的声明和函数原型说明:(1)如果在函数调用之前没有对函数作声明,则编译系统把第一次遇到的函数形式(函数定义或者函数调用)作为函数声明,并将函数类型默认为int型。(2)如果被调用函数的定义出现在主调用函数之前,可以不必加以声明。因为编译系统已经先知道了定义的函数类型,会根据函数首部提供的信息对函数的调用作正确性的检查。9.4.3对被调用函数的声明和函数原型(3)如果已在所有函数定义之前,在函数的外部已经做了函数声明,则在各个函数中不必对所调用的函数再作声明。9.4.3对被调用函数的声明和函数原型例2求两个任意整数中的最大值。9.4.3对被调用函数的声明和函数原型例3求两个任意整数之和,在函数的外部声明。9.5

函数的嵌套调用函数的嵌套调用——一个函数调用另一个函数,这个函数又调用另外一个函数,这样的调用称为函数的嵌套调用。

9.6

函数的递归调用9.6.1

递归的概念9.6.2

递归程序设计应用举例

9.6.1递归的概念递归——通俗地讲,用自身的结构来描述自身,就称为递归。递归调用——在调用一个函数的过程中,又出现直接地或间接地调用该函数本身,这种函数的调用称为递归调用。

9.6.2

递归程序设计应用举例

例1用递归求n!。

1n=0n!=n*(n-1)!n>09.6.2

递归程序设计应用举例

例2用递归调用的方法计算xn。

1n=0xn=

x*xn-1n>0

9.6.2

递归程序设计应用举例

例3

用递归求2个正整数的最大公约数。

辗转相除法:

nmModn=0

gcd(m,n)=

gcd(n,mModn)mModn≠0

9.7数组作为函数的参数

1.数组元素作函数参数

数组元素作函数参数——传值与用变量作实际参数一样,数组元素作函数的实际参数是单向传递,属于值传送。

9.7数组作为函数的参数例1求10个数中的最大值。

b——最大值9.7数组作为函数的参数

2.数组名作函数参数

数组名作函数参数——传地址9.7数组作为函数的参数说明:(1)如果形式参数是数组形式,则实际参数必须是实际的数组名,如果实际参数是数组名,则形式参数可以是同样维数的数组名或指针。(2)在主调用函数和被调用函数中分别定义数组。(3)实参数组和形参数组必须类型一致,形参数组可以不指明长度。9.7数组作为函数的参数(4)在C中,数组名除了作变量的标识符外,数组明换代表了该数组在内存中的起始地址,因此,当数组名作函数参数时,实参与形参之间是地址传递,实参数组名将该数组的起始地址传递给形参数组,两个数组共享相同的内存单元。编译系统不再为形参数组分配存储单元。9.7数组作为函数的参数例2在一个一维数组中存放10个学生的C语言程序设计的成绩,求平均成绩。9.7数组作为函数的参数例3用选择法对数组中的10个整数按从小到大的顺序排序。9.7数组作为函数的参数3.用多维数组名作函数参数用多维数组名作函数参数——传地址9.7数组作为函数的参数

例4求一个3×4矩阵中的最大元素。9.8局部变量和全局变量1.8.1

局部变量1.8.2

全局变量

9.8.1局部变量

局部变量——在一个函数内部定义的变量称为局部变量。它只在本函数范围内有效,只有在本函数中可以使用,在此函数以外不能使用这些变量。

9.8.1局部变量说明:(1)主函数main中定义的变量只能在主函数中有效。(2)不同函数中可以使用相同名字的变量,它们代表不同的对象,互不干扰。(3)形式参数也是局部变量。(4)在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效。

9.8.2全局变量全局变量——在函数之外定义的变量称为外部变量,外部变量是全局变量。全局变量可以为本文件中其他函数共用。它的有效范围为从定义变量的位置开始到本源文件结束。

9.9变量的的存储类别9.9.1

动态存储方式与静态存储方式9.9.2

auto变量用static声明的局部变量9.9.3

用static声明的局部变量register变量9.9.4

register变量9.9.5用extern声明的外部变量变量

9.9.1动态存储方式与静态存储方式

从变量的作用域(即从空间)来分,可以把变量分为全局变量与局部变量。

从变量值存在的时间(即生存期)来分,可以把变量分为静态存储方式和动态存储方式。

9.9.1动态存储方式与静态存储方式静态存储方式——指在程序运行期间分配固定的存储空间的方式。动态存储方式——是在程序运行期间根据需要进行动态的分配存储空间的方式。9.9.1动态存储方式与静态存储方式内存中提供用户使用的存储空间,这个存储空间分为3个部分:

1.程序区

2.静态存储区

3.动态存储区9.9.1动态存储方式与静态存储方式在动态存储区中存放以下数据:(1)函数的形式参数。(2)自动变量(未加static声明的局部变量)。(3)函数调用时保护现场和返回地址等。9.9.1动态存储方式与静态存储方式在C语言中数据的存储类别分为两大类:静态存储类和动态存储类。具体包含4种:自动的(auto)、静态的(static)、寄存器的(register)和外部的(extern)。根据变量的存储类别,可以确定变量的作用域和生存期。9.9.2auto变量自动变量——函数中的局部变量不说明存储类别的或者是用auto说明类别的变量称为自动变量。

9.9.3用static声明的局部变量静态局部变量——使用static说明其类别的局部变量称为静态局部变量。9.9.3用static声明的局部变量静态局部变量在函数调用结束后,函数中的局部变量的值不消失,保留原值,即不释放所占用的存储单元,在下一次调用函数时,静态局部变量已经有值,静态局部变量只初始化一次。9.9.3用static声明的局部变量

静态局部变量与自动局部变量的比较:(1)静态局部变量属于静态存储类别,在静态区内分配存储单元,在程序整个运行期间都不释放所占用的空间。而自动变量属于动态存储类别,在动态区内分配存储单元,在函数调用结束后释放所占用的空间。9.9.3用static声明的局部变量(2)静态局部变量只在编译时赋初值一次,以后没次调用函数时不再初始化变量,从而保留了上一次函数调用结束时的值。而自动变量不是在编译时赋初值,而是在调用函数时初始化变量,每调用一次函数就初始化一次。9.9.3用static声明的局部变量(3)静态局部变量不初始化,则编译系统自动对数值型变量赋初值0,对字符变量赋初空值。而自动变量不初始化,则它的值是一个不确定的诃子。这是由于每次函数调用结束后存储单元已经释放,下次调用时又重新另外反陪存储单元,而新分配的单元中的值是不确定的。9.9.3用static声明的局部变量那么,何时使用静态局部变量呢?(1)需要保留函数上一次调用的值。(2)如果初始化后,变量只被引用而不改变其值,这时使用静态局部变量比较方便,以免每次调用时重新赋值。

9.9.3用static声明的局部变量例1分析下列

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论