c程序设计第八章

上传人:壹****1 文档编号:569344039 上传时间:2024-07-28 格式:PPT 页数:69 大小:579.50KB
返回 下载 相关 举报
c程序设计第八章_第1页
第1页 / 共69页
c程序设计第八章_第2页
第2页 / 共69页
c程序设计第八章_第3页
第3页 / 共69页
c程序设计第八章_第4页
第4页 / 共69页
c程序设计第八章_第5页
第5页 / 共69页
点击查看更多>>
资源描述

《c程序设计第八章》由会员分享,可在线阅读,更多相关《c程序设计第八章(69页珍藏版)》请在金锄头文库上搜索。

1、掌握函数的定义,语法格式,函数调用;掌握函数的返回值,函数类型,被调用函数的说明以及函数原型;掌握形参和实参的概念,以及它们一一对应的关系;熟悉函数的嵌套调用和递归调用;掌握数组作为函数参数的使用;掌握内部变量和外部变量的定义;掌握动态变量和静态变量的存储方式;本章的教学目标本章的教学目标 第八章第八章 函函 数数 本章的教学重点本章的教学重点:熟练掌握函数的定义和调用方式熟练掌握函数的定义和调用方式理解和掌握函数参数的传递方式理解和掌握函数参数的传递方式掌握变量的作用域和存储类型掌握变量的作用域和存储类型本章的教学难点:本章的教学难点:函数的参数调用函数的参数调用对变量作用域和生存期的理解对

2、变量作用域和生存期的理解 教教 学学 任任 务务任务一任务一 函数概念的引入函数概念的引入; 任务二任务二 库函数库函数的的调用;调用; 任务三任务三 函数的定义函数的定义; 任务四任务四 函数间的参数传递函数间的参数传递;任务任务五五 函数的调用函数的调用 任务六任务六 数组与函数数组与函数 任务七任务七 变量的作用域变量的作用域任务八任务八 变量的存储类型变量的存储类型 任务九任务九 函数的存储分类函数的存储分类 任务一任务一 函数概念的引入函数概念的引入 一、一、C函数的概念函数的概念 将一个C程序分为若干模块,每个模块实现一个特定的功能,在C语言中用函数来实现模块的功能。 函数函数:具

3、有某种功能的独立程序段。 从程序设计方法看C函数:它是实现模块化程序设计的语法元素。从C语言中程序的组成方式看C函数:它是程序的基本组成单位。 二、二、C函数与函数与C程序结构程序结构 C程序由主函数(main函数)和若干个子函 数构成;主函数调用子函数;子函数在定义时是并列的;子函数可相互调用,也可被多次调用。mainabcdefghhiegvoid main( ) /* 主函数主函数 */ print_star(); /*调用调用print_star函数画函数画*/ print_message(); /*调用调用print _message函数写字函数写字*/ print_star();

4、/*调用调用print_star函数画函数画*/ void print_star() /*定义定义print_star函数函数*/ printf(“n*”); void print_message() /*定义定义print_message函数函数*/ printf(“n Hello! ”); 函数调用例:函数调用例:三、三、C函数的特点函数的特点 一个源文件由一个或多个函数组成,它是一 个独立编译单元。一个C程序由一个或多个源文件组成;C程序执行总是从main函数开始,调用其 他函数后流程回到main函数,在main函数 中结束整个程序的运行。函数不能嵌套定义,但可以互相调用。 注意不能调用

5、main函数。 四、函数的分类四、函数的分类 1. 从函数的参数形式看,函数可分为两类从函数的参数形式看,函数可分为两类: 无参函数; 有参函数 有参函数例:(输出两数中大者)#include int max( int x, int y ); main( ) int num1,num2,a; scanf(%d,%d,&num1,&num2); a = max(num1,num2); printf(max=%d,a); int max( int x, int y ) int z; if(xy) z=x; else z=y;return z;2. 从用户使用的角度看,函数有两种从用户使用的角度看,

6、函数有两种 :标准函数(库函数); 用户自己定义的函数 库函数:库函数:是由编译系统提供的已设计好的函数,是由编译系统提供的已设计好的函数,用户只需调用而无需要去实现它。前几章用过用户只需调用而无需要去实现它。前几章用过的的scanf,printf,getchar,putchar等都是库函等都是库函数。数。用户自定义函数:用户自定义函数:由程序员自己定义和设计的由程序员自己定义和设计的函数。需要程序员自己来编写函数功能实现代函数。需要程序员自己来编写函数功能实现代码。码。 任务任务二二 库函数的调用库函数的调用 调用库函数要用调用库函数要用调用库函数要用调用库函数要用includeinclud

7、e命令,其后要包括头文件名,命令,其后要包括头文件名,命令,其后要包括头文件名,命令,其后要包括头文件名,其一般形式:其一般形式:其一般形式:其一般形式: #include #include 例如: #include int x=10; abs (x);库函数调用的一般形式为;库函数调用的一般形式为; 库函数名(参数表)库函数名(参数表);函数名函数名含义含义用法用法absabs求整数的求整数的绝对值绝对值intint abs(intabs(int i); i);coscos求余弦函数求余弦函数double double cos(doublecos(double x); x);expexp求指

8、数函数求指数函数double double exp(doubleexp(double x); x);labslabs取取长长整型整型绝对值绝对值long long lasb(longlasb(long n); n);loglog求求对对数函数数函数long long double(xdouble(x) )powpow指数函数(指数函数(x x的的y y次方)次方)double double pow(doublepow(double x,doublex,double y); y);sinsin求正弦求正弦值值double double sin(doublesin(double x); x);sq

9、rtsqrt计计算平方根算平方根double double sqrt(doublesqrt(double x); x);tantan求正切求正切值值double double tan(doubletan(double x); x);itoaitoa把整型把整型转换为转换为字符型字符型char *char *itoa(intitoa(int value,charvalue,char * *string,intstring,int radix);radix);tolowertolower把字符把字符转换为转换为小写字母小写字母intint tolower(inttolower(int c); c)

10、;touppertoupper把字符把字符转换为转换为大写字母大写字母intint toupper(inttoupper(int c); c);randrand随机随机发发生器生器void void rand(voidrand(void); );gettimegettime取得当前系取得当前系统时间统时间void void gettime(structgettime(struct time time timeptimep); ); 表表1常用标准库函数常用标准库函数任务任务三三 函数的定义函数的定义 1. 无参函数的定义形式无参函数的定义形式类型标识符类型标识符 函数名()函数名() 声明部分

11、声明部分 执行部分执行部分 例如: print_message() printf(“n Hello!”);无参数传递无参数传递2. 有参函数的定义形式有参函数的定义形式类型标识符类型标识符 函数名(函数名(形式参数表列形式参数表列) 声明部分声明部分 执行部分执行部分 有参数传递有参数传递一、一、 函数的定义形式函数的定义形式例如:例如:int max (int x, int y) /*求求x和和y二者中大者,二者中大者,x,y为形参为形参*/ int z; /*函数体中变量的说明函数体中变量的说明*/ z=xy?x:y; return (z); /*将将z的值作为函数返回值的值作为函数返回值

12、*/3. 空函数的定义形式空函数的定义形式类型标识符类型标识符 函数名函数名( ) ( ) 例如:例如:dummy() 功能:调用后什么也不做。功能:调用后什么也不做。用处:建立程序结构,在需要时补充功能。用处:建立程序结构,在需要时补充功能。main() /* 主函数主函数 */ int m;printf(“please input number:n”);scanf(“%d”,&m); sum(m); /*调用求和函数调用求和函数*/ printf(“m=%dn”,m); void sum(int n) /*求和函数求和函数*/int i,result=0;for(i=1;iy?x:y; m

13、=mz?m:z; return(m);形参表形参表实参表实参表一、一、 形式参数和实际参数形式参数和实际参数上例中形参与实参、函数名与返回值之间的关系:上例中形参与实参、函数名与返回值之间的关系: c=max(a, b); - 实参实参:在运行时在运行时 把函数的把函数的 max(int x,int y) 把值传给函数把值传给函数。 结果赋给结果赋给 函数名函数名 returu (z); 形参形参:通知系统 要预留内存位置。 上面讲的形式参数表的说明形式是新版C语言表示形式(现代方式)现代方式),即即形式参数说明是类型和参数在一起说明。传统的形式参数说明是类型和参数分别说明。 如:按传统方式说

14、明形参 int max(x , y) int x,y; 按现代方式说明形参 int max(int x , int y) 这两种方式都可以使用,但推荐使用现代方式。 注意这里是逗号注意这里是逗号 实参可以是常量、变量或表达式,并且必须实参可以是常量、变量或表达式,并且必须 有确定的值;有确定的值; 对每个形参必须指明其名字和数据类型;对每个形参必须指明其名字和数据类型; 实参个数、类型必须与对应的形参一致;实参个数、类型必须与对应的形参一致; 形参是函数的内部变量,只在函数内部才有意义;形参是函数的内部变量,只在函数内部才有意义;实参对形参的数据传递是值传递,即单向传递,实参对形参的数据传递是

15、值传递,即单向传递, 只由实参传递给形参,反之不可。调用结束后,只由实参传递给形参,反之不可。调用结束后, 只有形参单元被释放,只有形参单元被释放,实参单元中的值不变实参单元中的值不变。 形参调用前不占内存单元,调用时占用形参调用前不占内存单元,调用时占用, 调用后调用后 释放;释放;关于参数的几点说明关于参数的几点说明:2. 参数的传递参数的传递调用一个函数时,调用函数和被调用函数之间会发生数据传递,有两种数据传递方式。一种是传值,另一种是传地址。如:按传值方式 int f(int x , inty) main() int a=3;int b=10; f(a,b); 按地址方式 void s

16、ort(int x , int n) main() int a5=0,1,2,5,6; sort(a,5); 1.传值传地址1.定义定义:通过函数调用使主调函数得到一个确定:通过函数调用使主调函数得到一个确定2. 的值,称为的值,称为函数的返回值函数的返回值。例如:例如: c=max(3, 5); 此时函数的返回值是此时函数的返回值是5,因此,因此c=52. 函数的返回值语句函数的返回值语句 return 函数的返回值是通过函数的返回值是通过 return语句语句 获得的。获得的。 return语句将被调函数的一个确定的值带回主语句将被调函数的一个确定的值带回主调函数中去。调函数中去。retu

17、rn语句的一般形式:语句的一般形式: return(函数返回值); return 函数返回值; “函数返回值”是有确定值的常量、变量或表达式。任务二、任务二、 函数的返回值函数的返回值说明说明:一个函数中可以有多个一个函数中可以有多个return语句,但是一次语句,但是一次 函数执行只能执行其中的一个。当执行到某个函数执行只能执行其中的一个。当执行到某个 return语句时,则终止函数执行,并带回函数语句时,则终止函数执行,并带回函数 值值。若函数体内没有若函数体内没有return语句,就一直将函数执行语句,就一直将函数执行 完,再返回调用函数,有一个不确定的值带回完,再返回调用函数,有一个不

18、确定的值带回。 return 后面的值可以是一个表达式,例如后面的值可以是一个表达式,例如: z=xy? x:y; return(z); return (xy? x:y); return后面可以无后面可以无“返回值返回值”(即(即 return ;),则则 该该return语句只起到语句只起到 终止函数执行,返回主调终止函数执行,返回主调 函数的作用。函数的作用。函数值的类型函数值的类型 函数定义时应该指定函数的类型函数定义时应该指定函数的类型(即函数值即函数值的类型),应该与的类型),应该与return语句的类型一致。语句的类型一致。说明说明:凡不加类型说明的函数,一律自动按整型处理。如果函

19、数类型和return语句的类型不一致,以函 数类型为准。对数值型数据,可以自动进行类型 转换。即函数类型决定返回值的类型。如果函数不返回值,可以将函数定义为“无类 型”void (或称“空类型”)。例如: void print_star()任务五任务五 函数的调用函数的调用 一、一、 函数调用的一般形式函数调用的一般形式 函数名(实际参数表) 有参数函数:无参数函数: 函数名() 说明说明:实际参数表中的参数可以是常量、变量或表达式; 实参与形参个数相等,类型应一致;多个实参间用逗号隔开;实参与形参按顺序对应,一一传递数据;实参表求值的顺序与系统有关。二、二、 函数调用方式函数调用方式 1.以

20、独立的函数语句调用以独立的函数语句调用 一般形式: 函数名(实际参数表); 这种方式常用于调用一个可以忽略返回值或没有返回值的函数。 使用情况: 如:我们程序中对scanf函数和printf函数的调用。 2. 函数调用出现在表达式(函数表达式)中函数调用出现在表达式(函数表达式)中。 一般形式: 变量名=函数表达式 使用情况: 这种方式用于调用带返回值的函数,函数的返回值将参加表达式的运算。 如:a =3+ max(num1,num2); 注意注意:无返回值函数的调用,不能出现在表达式中。 .函数参数函数参数 函数调用作为函数的参数,实质上是函数表达式形式调函数调用作为函数的参数,实质上是函数

21、表达式形式调用的一种,因为函数的参数本来就要求是表达式形式。用的一种,因为函数的参数本来就要求是表达式形式。 说明: 如:m=min (a, min (b,c); 函数调用的含义:函数调用的含义:函数作为一个函数的实际参数函数作为一个函数的实际参数()对实际参数列表中的每一个表达式求值。()对实际参数列表中的每一个表达式求值。()将表达式的值依次对应地赋给在被调用函数头部定义的形式参数()将表达式的值依次对应地赋给在被调用函数头部定义的形式参数变量。变量。()执行被调用函数的函数体。()执行被调用函数的函数体。()如果有()如果有return语句被执行,那么控制返回到主调函数中,如果语句被执行

22、,那么控制返回到主调函数中,如果return语句中包含表达式,将语句中包含表达式,将return语句中表达式的值返回到主调函数。语句中表达式的值返回到主调函数。()如果缺少()如果缺少return语句,那么在运行到函数体末尾时控制自动返回语句,那么在运行到函数体末尾时控制自动返回到主调函数。到主调函数。 三、三、 调用函数的声明调用函数的声明 对被调用函数说明的前提条件对被调用函数说明的前提条件 被调用函数必须是已存在的函数,如用户自定义函数或库函数。2. 被调用函数是用户自定义函数的函数说明被调用函数是用户自定义函数的函数说明 同变量一样,函数的调用也应该遵循“先说先说明,后使用明,后使用”

23、的原则。 如果使用用户自定义函数,而且主调函数和被调用函数在同一个文件中,应该在主调函数中说明被调函数的类型。其说明格式的一般形式如下:一般形式:类型标识符 函数名(类型1 形参1,类型2 形参2,); 类型标识符 函数名(类型1,类型2,); 或在C语言中,以上的函数说明称为函数原型函数原型。 main() float add(float x,float y); float a, b, c; scanf(“ %f, %f”, &a, &b); c=add(a,b) ; printf(“ sum is %f ”, c );/*定义定义add函数函数*/float add (float x,fl

24、oat y) float z; z=x+y; return (z); 对被调用函数的说明作为表达式被调用3. 被调用函数是库函数的函数说明被调用函数是库函数的函数说明 如果使用库函数,需要在文件的开头用#include 命令将需要的库函数包含到文件中。 现在我们清楚了,为什么在使用库函数之前必须包含相应的头文件?那是因为对这些库函数的原型说明全部都写在对应的头文件里了。 我们现在用到的头文件有:# include “stdio.h” /*调用输入输出函数调用输入输出函数*/# include “math.h” /*调用数学函数调用数学函数*/# include “string.h” /*调用字

25、符,字符串函数调用字符,字符串函数*/ 在本书的附录C中列出了C语言可以使用的标准库函数,大约有75个。请在阅读时注意形参的要求、功能及返回值。4. 函数说明和函数定义的区别函数说明和函数定义的区别 函数说明函数说明的作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。 旧版C语言函数说明只是对函数名极其返回类型的说明。如:float max();未进行全面检查,新版C语言兼容这种用法,但不提倡使用。 因此,下列函数说明都是合法的:float max(int x, int y); float max(int,int); float max

26、(); 函数定义函数定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。 5. 可省略被调用函数说明的三种情况可省略被调用函数说明的三种情况 函数的返回值为整型或字符型时,可以不进行 类型说明,系统按整型处理。 main( ) int a,b,c; scanf (“%d,%d”,&a,&b); c=max(a,b); printf(“Max is %d”,c); int max(int x,int y) int z; z=xy? x:y; return(z); 无函数说明无函数说明整型函数整型函数被调用函数定义在主调函数之前,可以不进行

27、 类型说明。 float add (float x, float y) float z; z=x+y; return (z); main() float a, b; scanf(“ %f, %f, “&a, &b); printf(“ sum is %f ”, add(a, b) ); 被调函数在主调函数之前被调函数在主调函数之前主调函数在被调函数之后主调函数在被调函数之后如果已在所有函数定义之前,在文件的开头, 在函数的外部已说明了函数类型,则在各个主 调函数中不必对所调用的函数再做说明。char letter( char,char);float f(float,float );int i(

28、float,float);main( ) .char letter (char c1,char c2)float f(float x,float y)int i(float,float)在所有函数之前在所有函数之前说明函数类型说明函数类型此处不必说明此处不必说明定义函数定义函数letter、f和和i四、函数的嵌套调用四、函数的嵌套调用 嵌套调用说明嵌套调用说明C语言不能嵌套定义函数,但可以嵌套调用函数,也就语言不能嵌套定义函数,但可以嵌套调用函数,也就是说,在调用一个函数的过程中调用另一个函数是说,在调用一个函数的过程中调用另一个函数。图图2嵌套函数执行流程嵌套函数执行流程2. 被调用函数是用

29、户自定义函数的函数说明被调用函数是用户自定义函数的函数说明 main函数 A函数 B函数 调用函数A 调用函数B 结束 返回主函数 返回函数A说明说明:执行过程见图中标号。执行过程见图中标号。 嵌套调用运用嵌套调用运用例例 函数嵌套的运用示例。函数嵌套的运用示例。#includeint fun1(int a,int b)int c;a+=a;b+=b;c=fun2(a,b); /*在函数在函数fun1中嵌套调用中嵌套调用fun2函数函数*/return (c*c);int fun2(int a,int b)int c;c=a*b%3;return c;void main()int x=2,y=

30、5;printf(“%dn”,fun1(x,y); /*输出的结果为输出的结果为1*/例例 用弦截法求方程的根用弦截法求方程的根 本例较复杂,重点是了解如何将本例较复杂,重点是了解如何将复杂的问题分解,然后在整合,复杂的问题分解,然后在整合,最终解决问题。最终解决问题。x2,f(x2)x1,f(x1)x,f(x) 数学函数(公式)为:数学函数(公式)为: y= f(x) = x 3-5x+16x-80 = 0问题可转化为:求曲线与问题可转化为:求曲线与x轴交点的轴交点的 x 坐标坐标1. 解题方法:解题方法:在曲线上取两点在曲线上取两点P和和 Q 坐标为坐标为(x1, f(x1) )和和( x

31、2,f(x2) ) ,如果如果f(x1) 和和f(x2)符号相反,则符号相反,则(x1 ,x2 )区间内必有区间内必有一根,反之,一根,反之, 改变改变 x1和和 x2 的值,直到的值,直到f(x1)和和f(x2) 异号异号为止。为止。求连接求连接P和和 Q 点的线段与点的线段与x轴的交点轴的交点x。 x =( x1* f(x2) - x2* f(x1) ) / ( f(x2) - f(x1) )如果如果 f(x) 和和 f(x1) 符号相同,符号相同, (x ,x2 )区间内必有一区间内必有一 根根,此时将此时将x作为新的作为新的x1。如果如果 f(x) 和和 f(x2) 符号相同符号相同

32、, (x 1,x )区间内必有一根区间内必有一根,此时将此时将x作为新的作为新的x2。重复步骤重复步骤 和和,不断缩小,不断缩小(x1 ,x2 )的距离,同时的距离,同时 f(x)越来越趋于越来越趋于0,直到,直到 | f(x) |0y1=y ; x1=xx2=x是是否否fabs(y)是是否否/*定义定义root函数的源程序函数的源程序*/float root (float x1, float x2) float x, y, y1; y1=f (x1); do x=xpoint(x1, x2); y=f(x); if (y*y10) y1=y; x1=x; else x2=x; while(f

33、abs(y)=0.0001 ); returu (x);/*定义主函数的源程序定义主函数的源程序*/void main()void main() float x1,x2,f1,f2,x; float x1,x2,f1,f2,x; do do printf(“inputprintf(“input x1,x2:n”); x1,x2:n”); scanf(“%f,%f”,&x1,&x2); scanf(“%f,%f”,&x1,&x2); f1=f(x1); f1=f(x1); f2=f(x2); f2=f(x2); while(f1*f2=0); while(f1*f2=0); x=root(x1,

34、x2); x=root(x1,x2); printf(“Aprintf(“A root of root of equaltionequaltion is %8.4fn”.x); is %8.4fn”.x); main输出根输出根x结结 束束调用调用 rootroot函数函数xpoint 函数函数f 函数函数调用调用xpoint调用调用 f11321231141059678上题函数的嵌套调用关系:上题函数的嵌套调用关系:在调用函数的过程中又出现直接或间接地调用该函数本在调用函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。身,称为函数的递归调用。 五、五、 函数的递归调用函数的递

35、归调用int func(float a)int x,y;y=func(x+y);return(x*y);void printletter()char c=Z;if(c=A)putchar(c);c-;printletter();有限次递归调用有限次递归调用有限次递归调用有限次递归调用无终止递归调用无终止递归调用无终止递归调用无终止递归调用说明:说明:不应出现无终止的递归调用,因此,应该不应出现无终止的递归调用,因此,应该 给定一个限制递归次数的条件。给定一个限制递归次数的条件。递归调用对应的一般算法:递归调用对应的一般算法:f(x)=终了公式终了公式递归公式递归公式递归函数的执行过程:递归函数

36、的执行过程:递归调用:记住本次现场,递归调用。终了调用:返回上次调用现场。例:用递归法求例:用递归法求n!算法:算法:f(n)=1 (n=1)f(n-1)*n (n1)main() int n,f; printf(“Input n :”); scanf(“%d”,&n); f= jx(n); printf(n n!=%d,f);int jx(int n) int f; if(n=1) f=1; else f=jx(n-1)*n; return f; 任务六任务六 数组与函数数组与函数 l数组元素做函数的实参数组元素做函数的实参l数组名做函数的参数数组名做函数的参数l二维数组可以做函数参数二维数

37、组可以做函数参数1. 数组元素可以做函数的实参数组元素可以做函数的实参 由于表达式可以做实参,数组元素可以由于表达式可以做实参,数组元素可以作为表达式的组成部分,因此,数组元素可作为表达式的组成部分,因此,数组元素可以做函数的实参,并且可以单向传递给形参。以做函数的实参,并且可以单向传递给形参。例:例:有两个数组有两个数组A,B。各有各有10个元素,将它们逐个个元素,将它们逐个对应相比,如果对应相比,如果A数组中的元素大于数组中的元素大于B数组中相应的数组中相应的元素数目多于元素数目多于B数组中的元素大于数组中的元素大于A数组中相应的元数组中相应的元素数目,则认为素数目,则认为A数组大于数组大

38、于B数组,并分别统计出两数组,并分别统计出两个数组相应元素大于,小于和等于的个数。个数组相应元素大于,小于和等于的个数。程序设计:程序设计:函数函数larger(x, y) :比较两个数组元素的比较两个数组元素的 大小。大小。 返回值返回值 flag=1 当 xy0 当 x=y-1 当 xy主函数主函数 :输入两个数组,调用输入两个数组,调用larger函数比较,计数,函数比较,计数,输出统计结果。输出统计结果。程序如下:程序如下:main ( ) int a10, b10, i, n=0, m=0, k=0; printf (“enter array a: n”); for ( i=0; i

39、10; i+) scanf(“%d”, &ai); printf (“ n”); printf (“enter array b: n”); for ( i=0;i10; i+) scanf(“%d”, &bi); printf (“ n”); for (i=0, i:%d n =: %d n k) printf(“abn”); else if (nk) printf(“ay) flag=1 else if (x: 4 =: 1 : 5 a b2. 数组名可以做函数的参数数组名可以做函数的参数 由于数组名代表的就是数组在内存中存放区域的首地址。把数组名作为函数参数来实现大量数据的传递是一个非常好

40、的数据传递方法。在主调函数和被调函数中分别定义数组;在主调函数和被调函数中分别定义数组;数组名可以做函数的参数的具体方法:数组名可以做函数的参数的具体方法:实参数组和形参数组类型应一致;实参数组和形参数组类型应一致;实参数组和形参数组大小不一定一致,形参数实参数组和形参数组大小不一定一致,形参数 组可以不指定大小(这里指一维数组)。组可以不指定大小(这里指一维数组)。说明说明:数组名做函数的实参和形参时不是:数组名做函数的实参和形参时不是“值传值传 递递”,而是,而是“地址传递地址传递”。因此,形参数。因此,形参数 组各元素的值如果发生变化会使实参数组组各元素的值如果发生变化会使实参数组 各元

41、素的值发生同样的变化。各元素的值发生同样的变化。例:用选择法对数组中例:用选择法对数组中10个整数按由小到大排序个整数按由小到大排序.程序设计:程序设计:函数函数sort(array, n) :对数组元素按由小到大排序。对数组元素按由小到大排序。主程序主程序 :输入输入array数组,调用数组,调用 sort 函数比较,输函数比较,输 出排序后的出排序后的array数组。数组。void sort (int array , int n) int v, j, k, t; for (i=0; in; i+) k=i; for (j=i+1; jn; j+) if (arrayjarrayk) k=j

42、; t=arrayk; arrayk=arrayi; arrayi=t; 这是数组作形参时常使用的技巧main ( ) int a10, i; printf(“enter array: n”); for (i=0; i10; i+) scanf (“ %d ”,&ai); sort(a, 10); printf(“the sorted array: n”); for (i=0; i10; i+) printf (“ %d ”, ai); printf(“n”);由于地址传递,地址传递,实参数组实参数组 a 改变改变数组名做参数的好处:数组名做参数的好处:由于只需复制一个地址值,而无须复制全部需

43、要处 理的数据,因此节约存储空间并提高效率。 由于主调函数和被调函数是在相同的内存区域上对 数据进行操作,因此可以实现数据的同步更新。 3 .多维数组可以做函数的参数多维数组可以做函数的参数l多维数组元素可以做实参多维数组元素可以做实参l多维数组名可以做参数多维数组名可以做参数说明说明:形参数组定义时可以指定或省略第一维的大小。形参数组定义时可以指定或省略第一维的大小。如如 : int array 310; 或或 int array 10; 但但 int array 3 ; 和和 int array ; 实参数组可以大于形参数组。实参数组可以大于形参数组。 如:实参数组定义为:如:实参数组定义

44、为:int array 510; 形参数组定义为:形参数组定义为:int array 310; 这时形参数组只取实参数组的一部分,这时形参数组只取实参数组的一部分,其余部分不起作用。其余部分不起作用。任务任务七七 变量的作用域变量的作用域一、一、 局部变量局部变量定义定义:在函数内部或复合语句内部定义的变量,称作局部变量局部变量。作用域作用域:函数内或复合语句内。 注意注意:主函数 main 定义的变量只在主函数中有效, 主函数不能使用其它函数定义的变量。不同函数中的同名变量互不影响。形参也是局部变量。 例例1: f1(int a) int b,c; 在本函数中在本函数中a a、b b、c c

45、有效有效 f2(int a,int b) int c,d; 在本函数中在本函数中 a a、b b、c c、d d有效有效 但与但与f1f1函数中的函数中的a a、b b、c c不同不同 main() int m,n; 在本函数中在本函数中m m、n n有效有效 例例2: main() int a,b; . int c c=a+b; a、b在此在此 c在此范围在此范围 范围内有效范围内有效 内有效内有效 . 二、二、 全局变量全局变量定义定义:在函数外部定义的变量称作全局变量全局变量 (也称外部变量)(也称外部变量)。 作用域作用域:可以为本文件中所有的函数公用。注意注意:从定义变量的位置开始到

46、本文件结束,这段从定义变量的位置开始到本文件结束,这段 程序中的函数可直接使用外部变量程序中的函数可直接使用外部变量。如果在定义点之前的函数想使用外部如果在定义点之前的函数想使用外部 变量,变量, 则应该在该函数中用关键字则应该在该函数中用关键字 extern 作作“外部外部 变量变量”说明。说明。如果在同一源文件中,外部变量和局部变量如果在同一源文件中,外部变量和局部变量 同名,则在局部变量的作用范围内,外部变同名,则在局部变量的作用范围内,外部变 量不起作用。量不起作用。从程序设计的观点看使用全局变量从程序设计的观点看使用全局变量 :优点:优点:增加了函数间数据联系增加了函数间数据联系 同

47、一文件中的一些函数引用全局变量,同一文件中的一些函数引用全局变量, 当某个函数中改变了全局变量的值,其当某个函数中改变了全局变量的值,其 它函数中的全局变量值也随之改变它函数中的全局变量值也随之改变。函数可以得到多个返回值函数可以得到多个返回值缺点:缺点:全局全局 变量在程序的全部执行过程中都占变量在程序的全部执行过程中都占 用存储单元。用存储单元。使用全局变量不符合程序设计中要求模块使用全局变量不符合程序设计中要求模块 间间“强内聚性、弱偶合性强内聚性、弱偶合性”的原则。的原则。使用全局变量过多,会降低程序的可读性使用全局变量过多,会降低程序的可读性 和可维护性。和可维护性。任务任务八八 变

48、量的存储类型变量的存储类型 一、一、 变量的动态和静态存储方式变量的动态和静态存储方式l静态存储方式:程序运行期间分配固定存储静态存储方式:程序运行期间分配固定存储 空间的方式。空间的方式。l动态存储方式:程序运行期间根据需要进行动态存储方式:程序运行期间根据需要进行 动态的分配存储空间的方式。动态的分配存储空间的方式。程序区程序区静态存储区静态存储区动态存储区动态存储区全局变量,局部静态变量全局变量,局部静态变量形式参数形式参数局部变量(自动)局部变量(自动)函数调用的现场函数调用的现场保护和返回地址保护和返回地址二、二、 静态存储变量和动态存储变量静态存储变量和动态存储变量l静态存储变量:

49、用静态存储方式存储的变量。静态存储变量:用静态存储方式存储的变量。l动态存储变量:用动态存储方式存储的变量。动态存储变量:用动态存储方式存储的变量。特点特点:在:在 静态存储区分配存储单元,整个程序静态存储区分配存储单元,整个程序 运行期间都不释放。运行期间都不释放。 特点特点:函数开始调用时为变量分配存储空间,:函数开始调用时为变量分配存储空间, 函数结束时释放这些空间。一个程序两函数结束时释放这些空间。一个程序两 次调用同一函数,其中同一个局部变量次调用同一函数,其中同一个局部变量 的内存地址可能不同的内存地址可能不同。C语言变量的属性:语言变量的属性:数据类型数据类型 存储类型存储类型存

50、储类型:数据在内存中的存储方式。存储类型:数据在内存中的存储方式。 即静态存储方式和动态存储方式。即静态存储方式和动态存储方式。 通过存储分类符来表示。通过存储分类符来表示。三、三、 变量的属性及其定义变量的属性及其定义数据类型数据类型:整型,实型,字符型整型,实型,字符型存储分类符:存储分类符:auto (自动的自动的)、register(寄存器的寄存器的)static (静态的静态的)、 extern(外部的外部的)定义变量的一般形式:定义变量的一般形式:存储分类符存储分类符 类型标识符类型标识符 变量名;变量名;如:auto int a; static int b; register i

51、nt d;1. auto(自动的)自动的)例如:在一函数内有定义例如:在一函数内有定义 auto int a; 则定义则定义a为自动变量(即存储类型是自为自动变量(即存储类型是自 动的)动的), 其数据类型是整型的。其数据类型是整型的。四、四、 局部变量的存储类型局部变量的存储类型auto只适用于说明局部变量只适用于说明局部变量,该局部变量是,该局部变量是 自动变量;自动变量; 自动变量存放在动态存储区,属于动态存储变量;自动变量存放在动态存储区,属于动态存储变量; 此类变量的作用域是其所在的函数内部,即程序此类变量的作用域是其所在的函数内部,即程序 在未进入函数之前或退出函数之后,其内部所定

52、在未进入函数之前或退出函数之后,其内部所定 义的所有自动变量都没有意义。义的所有自动变量都没有意义。说明:说明:在一个函数内如果局部变量不作存储类在一个函数内如果局部变量不作存储类 型说明,均为自动变量;型说明,均为自动变量;形式参数缺省存储类型是形式参数缺省存储类型是auto,但不能但不能 将将auto加在形参说明之前。加在形参说明之前。 如:如:int b, c=3 等价于等价于 auto int b, c=3; 如:如:int max(auto int x, auto int y) 2. static(静态的)静态的)static可用于说明可用于说明局部变量局部变量局部静态变量局部静态变

53、量全局变量全局变量外部静态变量外部静态变量局部静态变量局部静态变量 局部静态变量局部静态变量作用域仅限于定义它的函数内部作用域仅限于定义它的函数内部 。存放在静态存储区,存放在静态存储区,整个程序运行期间都不释放整个程序运行期间都不释放。 而自动变量函数调用结束后即释放。而自动变量函数调用结束后即释放。编译时赋初值,每次调用时不再赋初值,只保编译时赋初值,每次调用时不再赋初值,只保 留调用结束时变量的值。留调用结束时变量的值。 而自动变量调用一次,重新赋值一次。而自动变量调用一次,重新赋值一次。如果局部静态变量不赋初值,编译时自动赋如果局部静态变量不赋初值,编译时自动赋0。 而自动变量不赋初值

54、,其值不确定。而自动变量不赋初值,其值不确定。例如:打印1!5!int fac(int n) static int f=1; f=f*n; return(f)main() int i; for(i=1;i=5;i+) printf(“%d!=%dn”,i,fac(i);外部静态变量外部静态变量 外部静态变量只能在本源程序文件中被使用,外部静态变量只能在本源程序文件中被使用, 其他的源程序文件不能引用该静态全局变量。其他的源程序文件不能引用该静态全局变量。 全局变量(不论是否加全局变量(不论是否加static说明)编译时分配说明)编译时分配 在静态存储区。在静态存储区。 3. register(

55、寄存器的)寄存器的)寄存器寄存器:它是:它是CPU中运算器的组成部分,用来暂中运算器的组成部分,用来暂 时存放数据的存储装置。时存放数据的存储装置。寄存器变量寄存器变量:直接放置在运算器的寄存器中的变量直接放置在运算器的寄存器中的变量 称为寄存器变量。称为寄存器变量。引入寄存器变量引入寄存器变量 是为了提高是为了提高“存取存取”速度。速度。寄存器变量属于动态存储变量,但并不放在动态寄存器变量属于动态存储变量,但并不放在动态 存储区中,它放在寄存器中。存储区中,它放在寄存器中。 说明:说明:寄存器变量的作用域与自动变量相同。寄存器变量的作用域与自动变量相同。 regiser只适用于说明局部变量;

56、只适用于说明局部变量;例如:例如:register int i; 定义了定义了i是寄存器变量,其数据类型是整型的。是寄存器变量,其数据类型是整型的。由于计算机的寄存器数目有限,不宜定义太多由于计算机的寄存器数目有限,不宜定义太多 寄存器变量。不同的系统允许使用的寄存器个寄存器变量。不同的系统允许使用的寄存器个 数是不同的。数是不同的。 只有局部变量(非静态的)和形式参数可以作只有局部变量(非静态的)和形式参数可以作为寄存器变量。为寄存器变量。 例如:例如:register static int i; extern只适用于说明全局变量;只适用于说明全局变量;在多个源程序文件组成的程序中在多个源程

57、序文件组成的程序中 /*文件A.c*/ int a; main() 例如:例如: /*文件B.c*/ extern int a; power() 也可以写成extern a;如果如果B文件中引用在文件中引用在A文件中定义的全局变量文件中定义的全局变量 (该该 全局变量不是全局变量不是static变量变量),需要在),需要在B文件文件 中,用中,用 关键字关键字extern说明。说明。五、五、 全局变量的存储类型全局变量的存储类型在同一个源文件中在同一个源文件中,全局变量的作用域之外的函,全局变量的作用域之外的函 数中使用该全局变量时,也需用数中使用该全局变量时,也需用extern对其说明。对其

58、说明。 若在若在A文件中的全局变量是静态外部变量文件中的全局变量是静态外部变量(static),则即使在),则即使在B文件中用文件中用extern对其说明,也对其说明,也无法在无法在 A文件中使用该全局变量。文件中使用该全局变量。 /*文件A.c*/ static int a; main() 例如:例如: /*文件B.c*/ extern int a; power() 无法使用变量a任务任务九九 函数的存储分类函数的存储分类 一、一、 内部函数内部函数定义定义:如果一个函数只能被本文件中其它函数:如果一个函数只能被本文件中其它函数 调用,称为调用,称为内部函数内部函数(又称静态函数)。(又称静

59、态函数)。格式格式:static 类型标识符类型标识符 函数名(形参表)函数名(形参表)例如:例如:static int fun(a, b) . 作用作用:函数的作用域限于所在文件,不同文件中:函数的作用域限于所在文件,不同文件中 同名函数互不干扰,便于程序的局部化。同名函数互不干扰,便于程序的局部化。二、二、 外部函数外部函数定义定义:如果一个函数允许被其它文件调用,称:如果一个函数允许被其它文件调用,称 为为外部函数外部函数。格式格式: extern 类型标识符类型标识符 函数名(形参表)函数名(形参表)例如:例如:extern int fun(a, b) . int fun(a, b)

60、.或或 类型标识符类型标识符 函数名(形参表)函数名(形参表)或或通常不加通常不加 static 标识符的函数都是外部函数。标识符的函数都是外部函数。 在需要调用此函数的文件中,一般要用在需要调用此函数的文件中,一般要用extern说明所用的函数是外部函数。说明所用的函数是外部函数。 内内 容容 小小 结结 本章主要是讲解了有关于函数的一些基本知识。本章主要是讲解了有关于函数的一些基本知识。本章主要是讲解了有关于函数的一些基本知识。本章主要是讲解了有关于函数的一些基本知识。 在学习的在学习的在学习的在学习的过程要紧密结合本章的以下知识要点:过程要紧密结合本章的以下知识要点:过程要紧密结合本章的

61、以下知识要点:过程要紧密结合本章的以下知识要点:(1)(1)(1)(1)调调调调用用用用库库库库函函函函数数数数要要要要用用用用includeincludeincludeinclude命命命命令令令令,以以以以# # # #开开开开头头头头,文文文文件件件件名名名名需需需需要要要要用用用用一一一一对对对对双双双双引引引引号号号号或或或或一对尖括号一对尖括号一对尖括号一对尖括号括起来。括起来。括起来。括起来。(2) (2) (2) (2) 从函数的形式上看,函数分为两类:从函数的形式上看,函数分为两类:从函数的形式上看,函数分为两类:从函数的形式上看,函数分为两类: 无参无参无参无参函数;函数;

62、函数;函数;有参有参有参有参函数;函数;函数;函数;(3) (3) (3) (3) 从函数的值来看,函数分为两类:从函数的值来看,函数分为两类:从函数的值来看,函数分为两类:从函数的值来看,函数分为两类: 无返回值无返回值无返回值无返回值的函数:即的函数:即的函数:即的函数:即voidvoidvoidvoid函数。函数。函数。函数。 有返回值有返回值有返回值有返回值的函数:的函数:的函数:的函数: (4)(4)(4)(4)对对对对函函函函数数数数的的的的声声声声明明明明。通通通通常常常常在在在在函函函函数数数数调调调调用用用用之之之之前前前前,目目目目的的的的是是是是让让让让编编编编译译译译器

63、器器器利利利利用用用用这这这这些些些些信信信信息息息息去检查函数调用的合法性,保证参数的正确传递去检查函数调用的合法性,保证参数的正确传递去检查函数调用的合法性,保证参数的正确传递去检查函数调用的合法性,保证参数的正确传递 。(5)(5)(5)(5)函数参数的传递方式,有以下几种:函数参数的传递方式,有以下几种:函数参数的传递方式,有以下几种:函数参数的传递方式,有以下几种: 普通变量作为函数参数普通变量作为函数参数普通变量作为函数参数普通变量作为函数参数。 数组作为函数参数数组作为函数参数数组作为函数参数数组作为函数参数。(6)(6)(6)(6)函数的函数的函数的函数的递归调用和嵌套调用递归调用和嵌套调用递归调用和嵌套调用递归调用和嵌套调用。(7) (7) (7) (7) 变量的变量的变量的变量的作用域和存储类型作用域和存储类型作用域和存储类型作用域和存储类型。(8) (8) (8) (8) 函数的作用范围:函数的作用范围:函数的作用范围:函数的作用范围:内部内部内部内部函数和函数和函数和函数和外部外部外部外部函数。函数。函数。函数。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 资格认证/考试 > 自考

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号