1、第七章第七章 用函数实现模块化程序设计用函数实现模块化程序设计 交实验报告140页3题 格式:按照上机指导书171页附录D格式书写 采用统一的实验报告纸算法是解决具体问题的方案基本要求基本要求:根据给出的算根据给出的算法编写程序法编写程序7.1 为什么要用函数为什么要用函数实际的软件开发 实际问题往往由多个基本问题构成。要求软件开发人员首先分析问题,将问题分解为基本问题。其次,逐个解决每个基本问题。程序与问题的关系整个问题基本问题1基本问题n整个程序函数1函数n对软件开发人员的要求 分析并分解问题(高级要求)。设计解决基本问题的函数(基本要求)。例 iA 和 iB 为两个整数,iA 是基数,i
2、B 是指数.如何计算iBiA变量result保存最后结果,base为底数,exponent为指数。result=1;for(counter=1;counter=exponent;counter+)result*=base;计算35、55、85问题 如果要分别计算如果要分别计算100对整数的次幂,需要对整数的次幂,需要多少多少for?解决方案 我们制造一个零件(函数),它负责计算次幂 当需要计算次幂时,告诉零件基数和指数,零件返回结果。函数就象提供服务的人。iBiA 第一个角度:程序就是机器。函数就是零件。程序由函数构成。第二个角度:函数可以为其他函数提供服务,就象服务人员。1.什么是函数?函数
3、就是可以完成某项基本任务的一组语句。函数名是唯一的。函数可以被其他的函数使用,称为函数的调用。参数 主调用函数给被调用函数一些数据,即参数。被调用函数根据参数值完成相应的工作。返回值 被调用函数完成工作后,可能会返回某些数据作为计算结果。函数的要素 函数名 参数 返回值 函数体(语句)函数调用示例:函数调用示例:main()/*主函数主函数 */print_star();/*调用调用print_star函数画函数画*/print_message();/*调用调用print _message函数写字函数写字*/print_star();/*调用调用print_star函数画函数画*/print_
4、star()/*定义定义print_star函数函数*/prinf(“*n”);print_message()/*定义定义print_message函数函数*/prinf(“Hello!n”);运行结果:运行结果:*Hello!*一个源文件一个源文件由一个或多个函数组成,是由一个或多个函数组成,是一个独立编译单元。一个独立编译单元。一个一个C C程序程序由一个或多个源文件组成;由一个或多个源文件组成;C C程序执行总是从程序执行总是从mainmain函数开始,调用函数开始,调用其他函数后流程回到其他函数后流程回到mainmain。函数不能嵌套定义,但可互相调用。注函数不能嵌套定义,但可互相调用
5、。注意不能调用意不能调用mainmain函数。函数。函数的分类函数的分类 1.1.函数参数形式函数参数形式无参函数无参函数有参函数有参函数2.2.从用户使用的角度分从用户使用的角度分标准函数标准函数(库函数库函数)用户自己定义的函数用户自己定义的函数库函数库函数编译系统提供的已设计好的函数,用户只需调用而编译系统提供的已设计好的函数,用户只需调用而无需要去实现它无需要去实现它(scanf(scanf,printfprintf,getchargetchar,putcharputchar等等)。用户自定义函数用户自定义函数程序员自己定义和设计的函数。程序员自己定义和设计的函数。有参函数例有参函数例
6、(输出两数中大者输出两数中大者)#include main()int max(int x,int y);int n1,n2,a;scanf(%d,%d,&n1,&n2);a=max(n1,n2);printf(max=%d,a);int max(int x,int y)int z;if(xy)z=x;else z=y;return(z);无参函数例无参函数例main()print_star();print_message();print_star();print_star()prinf(“*n”);print_message()prinf(“Hello!n”);7.2 7.2 怎样定义函数怎样
7、定义函数 例如:例如:print_message()printf(“Hello!n”);二、二、有参函数的定义形式有参函数的定义形式类型标识符类型标识符 函数名(形参表列)函数名(形参表列)说明部分说明部分 语句语句 有参数传递有参数传递例如:例如:求求x和和y二者中大者二者中大者int max(int x,int y)/*x,y为形参为形参*/int z;/*函数体中变量的说明函数体中变量的说明*/z=xy?x:y;return(z);/*将将z的值作为函数返回值的值作为函数返回值*/类型标识符类型标识符 函数名()函数名()说明部分说明部分 语句语句 无参数传递无参数传递一、一、无参函数的
8、定义形式无参函数的定义形式三、三、空函数的定义形式空函数的定义形式类型标识符类型标识符 函数名函数名()()功能功能:调用后什么也不做。:调用后什么也不做。用处用处:建立程序结构,在需要时补充功能。:建立程序结构,在需要时补充功能。例如例如:dummy()若无参数,类型标识符写若无参数,类型标识符写void或不写或不写函数返回函数返回值的类型,值的类型,若不说明若不说明类型,默类型,默认为整型。认为整型。是被初始化的是被初始化的内部变量,寿内部变量,寿命和可见性仅命和可见性仅限于函数内部限于函数内部四、四、形式参数和实际参数形式参数和实际参数形式参数形式参数定义函数时函数名后面括弧中的变量名,
9、简称形参。定义函数时函数名后面括弧中的变量名,简称形参。实际参数实际参数调用函数时函数名后面括弧中的表达式,简称实参。调用函数时函数名后面括弧中的表达式,简称实参。c=max(a,b);-实参:实参:在运行时在运行时 把函数的把函数的 max(int x,int y)把值传给函数。把值传给函数。结果赋给结果赋给 函数名函数名 returu(z);形参:形参:通知系统通知系统 要预留内存位置要预留内存位置。上例中形参与实参、函数名与返回值之间的关系上例中形参与实参、函数名与返回值之间的关系main()int max(int x,int y);int a,b,c;scanf(“%d,%d,&a,&
10、b);c=max(a,b);printf(“Max is%d”,c);int max(int x,int y)int z;z=xy?x:y;return(z);形参表形参表实参表实参表函数的返回值语句函数的返回值语句returnreturn将被调函数的一个确定值带回主调函数。将被调函数的一个确定值带回主调函数。return(return(函数返回值函数返回值);或或 return return 函数返回值;函数返回值;通过函数调用使主调函数得到一个确定的值通过函数调用使主调函数得到一个确定的值五、函数的返回值五、函数的返回值main()int max(int x,int y);int a,b,
11、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);此时函数的返回值是此时函数的返回值是5,因此,因此c=5有确定值的常量、变有确定值的常量、变量或表达式量或表达式函数不加类型说明按整型处理函数不加类型说明按整型处理函数和函数和returnreturn类型不一致以类型不一致以函数类型为准。函数类型为准。函数不返回值定义为函数不返回值定义为voidvoid六、函数值的类型六、函数值的类型 void print_star()main()int max(i
12、nt x,int y);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);小结int (int iBase,int iExponent)返回类型:int 函数名:Power形式参数:iBase,iExponent形式参数的数值由实际参数决定。注意:int (int iBase,int iExponent)谁是被定义的函数?谁是参数?第一个int的作用是什么?后两个int的作用是什么?函数的使用者应该明确指明什么,才能使用函数?调用函
13、数就是使用函数。调用函数之前,必须首先声明函数。声明函数就是声明:函数名、函数返回值的类型和参数的类型。例:7.3 调用函数调用函数 一、函数调用的一般形式一、函数调用的一般形式 函数名(实际参数表)函数名(实际参数表)有参数函数有参数函数无参数函数无参数函数 函数名()函数名()void print_star()printf(“*”);main()int a,b,c;scanf(“%d,%d,&a,&b);c=2*max(a,b);print-star();printf(“c=%d”,c);int max(int x,int y)int z;z=xy?x:y;return(z);二、函数调用
14、的具体方式二、函数调用的具体方式1.1.函数调用作为一个语句函数调用作为一个语句 函数名(实际参数表);函数名(实际参数表);调用可忽略或没有返回值的函数调用可忽略或没有返回值的函数(如:如:scanf函数和函数和printf函数)函数)2.2.函数调用出现在表达式中函数调用出现在表达式中变量名变量名=函数表达式函数表达式调用带返回值的函数,其返回值调用带返回值的函数,其返回值参加表达式运算。参加表达式运算。无返回值函数的调用,不能出现无返回值函数的调用,不能出现在表达式中在表达式中3.3.函数参数函数参数 函数调用作为一个函数的参数。函数调用作为一个函数的参数。如:如:m=max(a,max
15、(b,c)m=max(a,max(b,c)在程序编译阶段在程序编译阶段,对调用函数的合法性进行对调用函数的合法性进行全面检查。如没有函数声明,编译到包全面检查。如没有函数声明,编译到包含函数调用的语句时(如含函数调用的语句时(如xx(a,b)),编),编译系统不知道译系统不知道xx是函数名,也无法判断是函数名,也无法判断实参(实参(a,b)的类型和个数是否正确,无)的类型和个数是否正确,无法进行正确性的检查。只有在运行时才法进行正确性的检查。只有在运行时才会发现实参与形参的类型或个数不一致,会发现实参与形参的类型或个数不一致,出现运行错误。出现运行错误。7.4、对被调用函数的声明和函数原型、对
16、被调用函数的声明和函数原型 对被调用函数说明的前提条件对被调用函数说明的前提条件必须是已存在的函数,如用户自定义函数或库函数。必须是已存在的函数,如用户自定义函数或库函数。2.2.被调用函数是用户自定义函数的函数说明被调用函数是用户自定义函数的函数说明主调函数和被调用函数在同一文件中,主调函数和被调用函数在同一文件中,在主调函数中说明被调函数类型。在主调函数中说明被调函数类型。在在C C语言中,以上的函数说明称为函数原型。语言中,以上的函数说明称为函数原型。/*定义定义add函数函数*/float add(float x,float y)float z;z=x+y;return(z);main
17、()float add(float x,float y);float a,b,c;scanf(“%f,%f”,&a,&b);c=add(a,b);printf(“sum is%f”,c);对被调用函数的说明对被调用函数的说明作为表达式被调用作为表达式被调用3.3.被调用函数是库函数的函数说明被调用函数是库函数的函数说明文件开头用文件开头用#include#include命令将调命令将调用库函数时需用到的信息用库函数时需用到的信息“包包含含”到文件中到文件中(对这些库函数对这些库函数的原型说明全部都写在对应的的原型说明全部都写在对应的头文件里头文件里)。常用的头文件:常用的头文件:#includ
18、e“stdio.h#include“stdio.h”#include“math.h”#include“math.h”#include“string.h”#include“string.h”4.4.省略被调用函数声明的三种省略被调用函数声明的三种情况情况 float add(float x,float y)float z;z=x+y;return(z);main()float a,b,c;scanf(“%f,%f”,&a,&b);c=add(a,b);printf(“sum is%f”,c);(1)被调函数定义在主函数前被调函数定义在主函数前(2)(2)函数返回值为整型或字符型,系统按整型处理。
19、函数返回值为整型或字符型,系统按整型处理。main()int a,b,c;scanf(“%d,%d”,&a,&b);c=max(a,b);printf(“Max is%d”,c);max(int x,int y)int z;z=xy?x:y;return(z);无函数说明无函数说明整型函数整型函数所有函数定义前,在函数的外部已说明函数类型。所有函数定义前,在函数的外部已说明函数类型。char letter(char,char);float f(float,float);int i(float,float);main().char letter(char c1,char c2)float f(f
20、loat x,float y)int i(float,float)在所有函数在所有函数之前说明函之前说明函数类型数类型此处不必说明此处不必说明定义函定义函数数letter、f和和i复习 函数的要素:名字、返回值、参数和代码 定义函数:编写代码 声明函数:声明名字、参数类型和返回值类型 调用函数:给出名字和实际参数,如果有返回值则保存。main()int i;long t;t=1;for(i=1;i=n;i+)t=t*i;printf(“n!=%ldn”,t);long xx(int x)long t=1;int i;if(x=0)printf(“error”);else for(i=1;i=x
21、,i+)t=t*i;return (t);main()int n;long s;scanf(“%d”,&n);s=xx(n);printf(“%ld”,s);例例1:编写函数,求:编写函数,求n!。例题例题1:求:求1+2+3+.+100的和。的和。main()int i,s=0;for(i=1;i=100;i+)s=s+i;printf(“s=%d”,s);例例2:编写函数,求:编写函数,求1+2+3+.n。int mm(int x)int t=0;int i;for(i=1;i=x,i+)t=t+i;return (t);main()int n;int s;scanf(“%d”,&n);s
22、=mm(n);printf(“%d”,s);执行细节-步骤 1.程序将从主函数开始执行2.当发生函数调用时,主调用函数暂停3.实际函数的值将被复制给形式参数(不需要任何语句,程序自动做该项工作).4.被调用函数执行5.遇到返回语句时,被调用函数将结果返回给主调用函数6.主调用函数恢复执行执行细节-存储分配 被调用函数执行前,系统为其变量分配内存空间(包括形式参数)。实际参数的值被复制给形式参数(值传递).当被调用函数结束执行后,内存空间将被释放,下次调用时重新分配。例:你可以判断出下面程序的结果吗?程序的执行过程是怎样的?void Swap(int iA,int iB)int iTemp;iT
23、emp=iA;iA=iB;iB=iTemp;main()int iFirst=13,iSecond=27;Swap(iFirst,iSecond);printf(niA is%d,iFirst);printf(niB is%d,iSecond);main()int iFirst=13;int iSecond=27;Swap(iFirst,iSecond);printf(niFirst is%d,iFirst);printf(niSecond is%d,iSecond);iFirst=13iSecond=27iFirst=13iSecond=27iB=27iA=13iTempmain()int
24、iFirst=13;int iSecond=27;Swap(iFirst,iSecond);printf(niFirst is%d,iFirst);printf(niSecond is%d,iSecond);void Swap(int iA,int iB)int iTemp;iTemp=iA;iA=iB;iB=iTemp;iFirst=13iSecond=27iB=27iA=13iTempiFirst=13iSecond=27iB=13iA=27iTempmain()int iFirst=13;int iSecond=27;Swap(iFirst,iSecond);printf(niFirst
25、 is%d,iFirst);printf(niSecond is%d,iSecond);iFirst=13iSecond=27总结 参数传递的时候,实际参数的数值复制给形式参数 形式参数是实际参数的“复印件”。修改形式参数,不影响实际参数的数值。这一机制称为:call-by-value7.5 7.5 函数的嵌套调用函数的嵌套调用C语言不能嵌套定义,但可以嵌套调用。语言不能嵌套定义,但可以嵌套调用。嵌套定义:在定义一个函数时,该函数体内包含嵌套定义:在定义一个函数时,该函数体内包含 另一个函数的定义。另一个函数的定义。一一.嵌套调用嵌套调用调用一个函数的过程中,又调用另一个函数。调用一个函数的过
26、程中,又调用另一个函数。main函数函数调用调用A函数函数结结 束束A函数函数调用调用B函数函数B函数函数192873456例题:编写函数,求例题:编写函数,求1!+3!+5!+.k!其中其中k是小于是小于9的奇数,要求该的奇数,要求该函数中调用求阶乘函数求出各阶乘的值。函数中调用求阶乘函数求出各阶乘的值。double xx(int x)double t=1;int i;for(i=1;i=x,i+)t=t*i;return (t);double yy(int m)double s=0;int i;for(i=1;i1)main()double jx(int m)int n;double t;
27、printf(“Input n:”);scanf(“%d”,&n);t=jx(n);printf(%f,t);double jx(int m)double f;if(m=1)f=1;else f=jx(m-1)*m;return f;数组作参数的时候,函数可以使用数组元素的“原件”。数组的存储原理决定了这一效果。例:7.7 数组作为函数参数数组作为函数参数 数组的存储原理100010021004100610081020304050iList0iList1iList2iList3iList4数组元素的地址 如果数组iList存储在1000开始的内存空间,那么 1000是iList0的地址,100
28、2是iList1的地址,1004是iList2的地址。请问,iListi的地址?1000+i*2计算机访问数组元素的原理 计算机根据数组的首地址、元素的下标和数据元素在内存的长度,计算元素的地址,然后根据地址访问数组元素。元素的下标由程序员指定。元素的类型是预先声明的。数组的首地址保存在数组名中。数组名就是数组的首地址。计算机访问数组元素的原理 访问iListi,就是访问地址为iList+i*sizeof(int)其中,iList是首地址,i是元素的下标,sizeof(int)是元素在内存的长度(字节为单位)。问题 如果iArray也是数组名,而且iArray中存储的地址与iList相同,那么
29、iArrayi与iListi有什么关系?答:它们是同一数据元素。一、数组元素做函数实参一、数组元素做函数实参例题:有两个数组例题:有两个数组A A,B B各有各有1010个元素,将它们逐个对应相比,个元素,将它们逐个对应相比,如果如果A A数组中的元素大于数组中的元素大于B B数组中相应的元素数目多于数组中相应的元素数目多于B B数组中的数组中的元素大于元素大于A A数组中相应的元素数目,则认为数组中相应的元素数目,则认为A A数组大于数组大于B B数组,并数组,并分别统计出两个数组相应元素大于,小于和等于的个数。分别统计出两个数组相应元素大于,小于和等于的个数。程序设计:程序设计:1、函数、
30、函数large(x,y):比较两个数组元素的:比较两个数组元素的 大小。大小。返回值返回值 flag=1 当当 xy0 当当 x=y-1 当当 xy)flag=1;else if(x:4 =:1 :5 a bmain()int a10,b10,i,n=0,m=0,k=0;for(i=0;i10;i+)scanf(“%d”,&ai);for(i=0;i10;i+)scanf(“%d”,&bi);for(i=0;ik)printf(“abn”);else if(nk)printf(“abn”);else printf(“a=bn”);二、数组名做函数参数二、数组名做函数参数数组名代表数组在内存中存
31、放区域首地址。数组数组名代表数组在内存中存放区域首地址。数组名作函数参数实现大量数据传递。名作函数参数实现大量数据传递。数组名做函数的参数方法:数组名做函数的参数方法:在主调函数和被调函数中分别定义数组;在主调函数和被调函数中分别定义数组;实参数组和形参数组类型应一致;实参数组和形参数组类型应一致;实参数组和形参数组大小不一定一致,形参数实参数组和形参数组大小不一定一致,形参数 组可以不指定大小(这里指一维数组)。组可以不指定大小(这里指一维数组)。说明说明数组名做函数的实参和形参时是数组名做函数的实参和形参时是“地址传递地址传递”。形参数组各。形参数组各元素的值发生变化会使实参数组各元素值发
32、生同样的变化。元素的值发生变化会使实参数组各元素值发生同样的变化。例例1:编写函数,求一维数组中存放学生成绩的平均值。:编写函数,求一维数组中存放学生成绩的平均值。float aver(float a ,int n )int i;float pj,sum=0;for(i=0;in;i+)sum=sum+ai;pj=sum/n;return(pj);main()float xs10,pjf;int i;for(i=0;i10;i+)scanf(“%f”,&xsi);pjf=aver(xs,10);printf(“pjf=%f”,pjf);一维数组作函数一维数组作函数参数时形参数组参数时形参数组可
33、不指定大小可不指定大小一维数组的大小一维数组的大小把一维数把一维数组组xs的首的首地址传给地址传给形参数组形参数组a例例2 2:对数组中:对数组中1010个整数按由小到大排序。个整数按由小到大排序。void sort(int array,int n)int v,j,t;for(i=0;in-1;i+)for(j=i+1;jn;j+)if(arrayjarrayk)t=arrayk;arrayk=arrayi;arrayi=t;main()int a10,i;for(i=0;i10;i+)scanf(“%d”,&ai);sort(a,10);for(i=0;i10;i+)printf(“%d”,
34、ai);由于地址传递,地址传递,实参数组实参数组 a 改变改变例例3:写一函数,使给定的一个二维整形数组(:写一函数,使给定的一个二维整形数组(3*3)转置,即行列互换。)转置,即行列互换。void xx(int a33 )int i,j;for(i=0;i3;i+)for(j=0;j3;j+)printf(“%d”,aji;)printf(“n”);main()int a33,i,j;for(i=0;i3;i+)for(j=0;j3;j+)scanf(“%d”,&aij);xx(a);二维数组名做函数参二维数组名做函数参数数,可以指定每一维,可以指定每一维的大小或省略第一维的大小或省略第一维
35、的大小的大小如如:int array 310;或或 int array 10;但但 int array 3 ;和和 int array ;总结 当数组的名字作为形式参数时,被复制的是数组的首地址 函数根据首地址处理的是数组元素的“原件”,而不是“复印件”。7.8 局部变量和全局变量局部变量和全局变量在函数内部或复合语句内部定义的变量在函数内部或复合语句内部定义的变量作用域:函数内或复合语句内。作用域:函数内或复合语句内。局部变量局部变量主函数主函数 main 定义的变量只在主函数中有效,定义的变量只在主函数中有效,主函数不能使用其它函数定义的变量。主函数不能使用其它函数定义的变量。不同函数中的
36、同名变量互不影响。不同函数中的同名变量互不影响。形参也是局部变量。形参也是局部变量。在本函数中在本函数中a a、b b、c c有效有效f1(int a)int b,c;在本函数中在本函数中a a、b b、c c、d d有效有效但与但与f1f1函数中的函数中的a a、b b、c c不同不同f1(int a,int b)int d,c;在本函数中在本函数中m m、n n有效有效main()int m,n;例:例:main()int a=10,b=10;int c c=a+b;a、b在此在此 c在此范围在此范围 范围内有效范围内有效 内有效内有效 .在函数外部定义的变量(也称外部变量)在函数外部定义
37、的变量(也称外部变量)。作用域:可以为本文件中所有的函数公用。作用域:可以为本文件中所有的函数公用。全局变量全局变量从定义变量的位置开始到本文件结束,从定义变量的位置开始到本文件结束,这段程序中的函数可直接使用外部变量。这段程序中的函数可直接使用外部变量。如果在定义点之前的函数想使用外部如果在定义点之前的函数想使用外部 变变量,则应该在该函数中用关键字量,则应该在该函数中用关键字 extern extern 作作“外部变量外部变量”说明。说明。如果在同一源文件中,外部变量和局部如果在同一源文件中,外部变量和局部变量同名,则在局部变量的作用范围内,变量同名,则在局部变量的作用范围内,外部变量不起
38、作用。外部变量不起作用。优点优点增加了函数间数据联系同一文件中的一些函数引用全局变量,增加了函数间数据联系同一文件中的一些函数引用全局变量,当某个函数中改变了全局变量的值,其它函数中的全局变量值也当某个函数中改变了全局变量的值,其它函数中的全局变量值也随之改变。随之改变。函数可以得到多个返回值函数可以得到多个返回值缺点缺点全局全局 变量在程序的全部执行过程中都占用存储单元。变量在程序的全部执行过程中都占用存储单元。使用全局变量不符合程序设计中要求模块间使用全局变量不符合程序设计中要求模块间“强内聚性、弱偶强内聚性、弱偶合性合性”的原则。的原则。使用全局变量过多,会降低程序的可读性和可维护性。使
39、用全局变量过多,会降低程序的可读性和可维护性。变量的存储类别变量的存储类别 1.静态存储方式和动态存储方式静态存储方式和动态存储方式l静态存储方式:程序运行期间分配固定存储静态存储方式:程序运行期间分配固定存储 空间的方式。空间的方式。l动态存储方式:程序运行期间根据需要进行动态存储方式:程序运行期间根据需要进行 动态的分配存储空间的方式。动态的分配存储空间的方式。程序区程序区静态存储区静态存储区动态存储区动态存储区全局变量,局部静态变量全局变量,局部静态变量形式参数形式参数局部变量(自动)局部变量(自动)函数调用的现场函数调用的现场保护和返回地址保护和返回地址7.9 变量的存储方式和生存期变
40、量的存储方式和生存期2.静态存储变量和动态存储变量静态存储变量和动态存储变量l静态存储变量:用静态存储方式存储的变量。静态存储变量:用静态存储方式存储的变量。l动态存储变量:用动态存储方式存储的变量。动态存储变量:用动态存储方式存储的变量。特点:在特点:在 静态存储区分配存储单元,整个程序静态存储区分配存储单元,整个程序 运行期间都不释放。运行期间都不释放。特点:函数开始调用时为变量分配存储空间,特点:函数开始调用时为变量分配存储空间,函数结束时释放这些空间。一个程序两函数结束时释放这些空间。一个程序两 次调用同一函数,其中同一个局部变量次调用同一函数,其中同一个局部变量 的内存地址可能不同。
41、的内存地址可能不同。C语言变量的属性:语言变量的属性:数据类型数据类型 存储类型存储类型存储类型:数据在内存中的存储方式。存储类型:数据在内存中的存储方式。即静态存储方式和动态存储方式。即静态存储方式和动态存储方式。3.变量的属性及其定义变量的属性及其定义数据类型:整型,实型,字符型数据类型:整型,实型,字符型存储分类符:存储分类符:auto(自动的自动的)、register(寄存器的寄存器的)static(静态的静态的)、extern(外部的外部的)定义变量的一般形式:定义变量的一般形式:存储分类符存储分类符 类型标识符类型标识符 变量名;变量名;如:auto int a;static in
42、t b;register int d;auto(自动的)自动的)例如:例如:auto int a;4.变量的存储类型变量的存储类型auto说明局部变量,该局部变量是自动变量;说明局部变量,该局部变量是自动变量;自动变量存放在动态存储区,属于动态存储变量;自动变量存放在动态存储区,属于动态存储变量;变量作用域是其所在的函数内部。变量作用域是其所在的函数内部。说明:说明:在一个函数内如果局部变量不作存储类在一个函数内如果局部变量不作存储类 型说明,均为自动变量;型说明,均为自动变量;形式参数缺省存储类型是形式参数缺省存储类型是auto,但不能,但不能 将将auto加在形参说明之前。加在形参说明之前
43、。如:如:int b,c=3 等价于等价于 auto int b,c=3;如:如:int max(auto int x,auto int y)static(静态的)静态的)static可用于说明可用于说明局部变量局部变量局部静态变量局部静态变量全局变量全局变量外部静态变量外部静态变量局部静态变量局部静态变量 作用域仅限于定义它的函数内部作用域仅限于定义它的函数内部。存放在静态存储区,整个程序运行期间都不释放。存放在静态存储区,整个程序运行期间都不释放。编译时赋初值,每次调用不再赋初值,只保留调用结束时变编译时赋初值,每次调用不再赋初值,只保留调用结束时变量的值。量的值。自动变量调用一次,重新赋
44、值一次。自动变量调用一次,重新赋值一次。局部静态变量不赋初值,编译时自动赋局部静态变量不赋初值,编译时自动赋0。自动变量不赋初值,其值不确定。自动变量不赋初值,其值不确定。例如:打印例如:打印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说明,编译时分配在静态存储区。说明,编译时分配在静态存储区。register(寄存器的)寄存
45、器的)寄存器:寄存器:CPU中运算器的组成部分,暂时存放数据。中运算器的组成部分,暂时存放数据。寄存器变量:直接放置在运算器的寄存器中的变量。引入寄寄存器变量:直接放置在运算器的寄存器中的变量。引入寄 存器变量是为了提高存器变量是为了提高“存取存取”速度。速度。属于动态存储变量,但不放在动态存储区中,放在寄存器中。属于动态存储变量,但不放在动态存储区中,放在寄存器中。说明:说明:寄存器变量的作用域与自动变量相同。寄存器变量的作用域与自动变量相同。regiser只适用于说明局部变量;只适用于说明局部变量;例如:例如:register int i;定义了定义了i是寄存器变量。是寄存器变量。计算机的
46、寄存器数目有限,不宜定义太多寄存器变量。不同计算机的寄存器数目有限,不宜定义太多寄存器变量。不同的系统允许使用的寄存器个数是不同的。的系统允许使用的寄存器个数是不同的。只有局部变量(非静态的)和形参可以作为寄存器变量。只有局部变量(非静态的)和形参可以作为寄存器变量。例如:例如:register static int i;exturn(外部的)外部的)exturn适用于说明全局变量;适用于说明全局变量;在多个源程序文件组成的程序中在多个源程序文件组成的程序中 /*文件A.c*/int a;main()例如:例如:/*文件B.c*/exturn int a;power()也可以写成exturn
47、a;如果如果B文件中引用在文件中引用在A文件中定义的全局变量文件中定义的全局变量(该该 全局变量不是全局变量不是static变量),需要在变量),需要在B文件文件 中,用中,用 关键字关键字extern说明。说明。在同一个源文件中,全局变量的作用域之外的函在同一个源文件中,全局变量的作用域之外的函 数中使用该全局变量时,也需用数中使用该全局变量时,也需用extern对其说明。对其说明。若在若在A文件中的全局变量是静态外部变量(文件中的全局变量是静态外部变量(static),则即使在,则即使在B文件中用文件中用extern对其说明,也无法在对其说明,也无法在 A文件中使用该全局变量。文件中使用该
48、全局变量。/*文件A.c*/static int a;main()例如:例如:/*文件B.c*/exturn int a;power()无法使用变量a7.11 内部函数和外部函数内部函数和外部函数 一、内部函数一、内部函数定义:如果一个函数只能被本文件中其它函数定义:如果一个函数只能被本文件中其它函数 调用,称为内部函数(又称静态函数)。调用,称为内部函数(又称静态函数)。格式:格式:static 类型标识符类型标识符 函数名(形参表)函数名(形参表)例如:例如:static int fun(a,b).作用:函数的作用域限于所在文件,不同文件中作用:函数的作用域限于所在文件,不同文件中 同名函
49、数互不干扰,便于程序的局部化。同名函数互不干扰,便于程序的局部化。二、外部函数二、外部函数定义:如果一个函数允许被其它文件调用,称定义:如果一个函数允许被其它文件调用,称 为外部函数。为外部函数。格式:格式:exturn 类型标识符类型标识符 函数名(形参表)函数名(形参表)例如:例如:exturn int fun(a,b).int fun(a,b).或或 类型标识符类型标识符 函数名(形参表)函数名(形参表)或或通常不加通常不加 static 标识符的函数都是外部函数。标识符的函数都是外部函数。在需要调用此函数的文件中,一般要用在需要调用此函数的文件中,一般要用exturn说明说明所用的函数是外部函数。所用的函数是外部函数。
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。