《c语言(第八章函数).ppt》由会员分享,可在线阅读,更多相关《c语言(第八章函数).ppt(81页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第八章第八章 函数函数z函数定义的一般形式函数定义的一般形式 z函数参数和函数的值函数参数和函数的值 z函数的调用函数的调用 z数组作为函数参数数组作为函数参数z函数的嵌套调用函数的嵌套调用 函数的递归调用函数的递归调用z局部变量和全局变量局部变量和全局变量 z内部函数和外部函数内部函数和外部函数 8.1 概概 述述main()scanf()printf()max()x()printf()y()getchar()max()main()star();message();star();star()printf(*n);message()printf(game over!n);1、一个源文件由一个或
2、、一个源文件由一个或多个函数组成。是一个编多个函数组成。是一个编译单位。译单位。2、一个、一个C程序由一个或多程序由一个或多个源文件组成。个源文件组成。3、C程序的执行由程序的执行由main函数开始,调用其他函数函数开始,调用其他函数后回到后回到main函数。函数。4、所有的函数都是平行、所有的函数都是平行的,在定义的时候相互独的,在定义的时候相互独立。一个函数并不从属于立。一个函数并不从属于另一个函数。另一个函数。5、从用户角度看,函数、从用户角度看,函数有两种:标准函数(库函有两种:标准函数(库函数)、用户自定义函数。数)、用户自定义函数。有返回值有返回值无返回值无返回值无参函数无参函数有
3、参函数有参函数函数的分类:函数的分类:1、根据有无返回值分、根据有无返回值分:2、根据函数有无参数来分、根据函数有无参数来分:8.2 函数定义的一般形式函数定义的一般形式z1.无参函数定义一般形式无参函数定义一般形式 类型标识符类型标识符 函数名函数名()说明部分说明部分 语句语句 例如例如:nihao()/*nihao函数函数,功能:显示一字符串功能:显示一字符串*/printf(How do you do!n);该函数无形式参数列表该函数无形式参数列表类型标识符指定函数值的类型,即函数带回来的值的类型标识符指定函数值的类型,即函数带回来的值的类型。如果省略,系统隐含指定为类型。如果省略,系
4、统隐含指定为int 型。型。例如例如:int max(int x,int y)int z;/*函数内部定义的变量函数内部定义的变量*/z=xy?x:y;return(z);/*return语句使函数结束执行,返回主调函数,语句使函数结束执行,返回主调函数,括号的的括号的的z值作为函数带回的值(返回值)。值作为函数带回的值(返回值)。*/z2.2.有参函数定义一般形式有参函数定义一般形式 类型标识符类型标识符 函数名函数名(形式参数列表)(形式参数列表)说明部分说明部分 语句语句 类型标识符类型标识符 函函 数数 名名形式参数列表形式参数列表,该函数有该函数有两个形式参数,均为整型两个形式参数,
5、均为整型3 3、函数定义的其他形式、函数定义的其他形式z1).可以有空函数可以有空函数 int dummy()z2).无返回值函数无返回值函数 void doit(.).类型标识符说明为类型标识符说明为void,表示函数无返回值,即该,表示函数无返回值,即该函数执行后不返回任何值。函数执行后不返回任何值。无形式参数无形式参数函数体中无任何语句函数体中无任何语句,称为称为“空函数空函数8.3 函数参数和函数的值函数参数和函数的值一、形式参数和实际参数一、形式参数和实际参数z形形 式式 参参 数数:在在 定定 义义 函函 数数 时时 使使 用用 的的 参参 数数,简称简称“形参形参”。形参是一个变
6、量形参是一个变量.z实际参数:在调用函数时使用的参数,实际参数:在调用函数时使用的参数,简称简称“实参实参”。实参是一个表达式实参是一个表达式.主调用函数与被调用函数之间的数据传递,主调用函数与被调用函数之间的数据传递,就就是是通通过过形形参参与与实实参参之之间间的的数数据据传传递递实实现现的。的。例例8.1、输入两个整数,求它们的最大值。、输入两个整数,求它们的最大值。求最大值用函数求最大值用函数max实现。实现。main()int a,b,c;scanf(%d,%d,&a,&b);c=max(a,b);printf(max is%dn,c);int max(int x,int y)int
7、z;z=xy?x:y;return(z);max(a,b)main()函数函数max函数函数max(x,y)return(z)计算计算zx和和y是形式参数是形式参数a和和b是实际参数是实际参数关于形参与实参的说明:关于形参与实参的说明:1、在定义函数中指定的形参,在未发生函数调、在定义函数中指定的形参,在未发生函数调用时,不占内存空间。它们是用时,不占内存空间。它们是动态分配动态分配的。的。2、实参可以是常量、变量或表达式,在函数调、实参可以是常量、变量或表达式,在函数调用时,将实参的值传给形参变量。用时,将实参的值传给形参变量。3、在被定义的函数中,必须指定形参的类型。、在被定义的函数中,必
8、须指定形参的类型。如:如:int max(int x,int y)4、实参与形参的类型应相同或赋值兼容。、实参与形参的类型应相同或赋值兼容。5、C语言规定,实参变量对形参变量的数据语言规定,实参变量对形参变量的数据传递是传递是“值传递值传递”,既,既单向传递单向传递,只有实参,只有实参传给形参,而不能由形参传回来给实参。传给形参,而不能由形参传回来给实参。如下图:如下图:2323a b x y2332a b x y二、函数的返回值二、函数的返回值z1、函数中的、函数中的return语句返回函数的值,一个函数可语句返回函数的值,一个函数可以有一个以上的以有一个以上的return语句,执行到哪一个
9、语句,执行到哪一个return语语句,哪个句,哪个return语句就起作用。语句就起作用。例如:例如:max(int x,int y)return(xy?x:y);或或max(int x,int y)if(xy)return x;else return y;z2、定义函数时,应定义函数时,应指明函数(返回值)类型指明函数(返回值)类型,若未指名,系统认为返回值类型为若未指名,系统认为返回值类型为int。例如:例如:int max(int x,int y)float min(char a,char b)z3、如果函数的返回值声明与如果函数的返回值声明与return语句中表语句中表达式的类型不同,
10、达式的类型不同,以函数的返回值声明为准以函数的返回值声明为准,系统将自动进行转换。系统将自动进行转换。main()float a,b;int c;scanf(“%f,%f”,&a,&b);c=max(a,b);printf(“Max is%dn”,c);max(float x,float y)float z;z=xy?x:y;return z;运行结果:运行结果:1.5,2.5Max is 2z4、只要函数只要函数定义了返回值类定义了返回值类型,无论函数中型,无论函数中是否有是否有return语语句,函数均返回句,函数均返回一个值。下面语一个值。下面语句也是合法的:句也是合法的:main()i
11、nt a,b,c;a=star();b=message();c=star();printf(“%d,%d,%d”,a,b,c);star()printf(*n);message()printf(game over!n);z5、为了明确规定为了明确规定函数不返回任何值函数不返回任何值,在,在函数定义中,函数定义中,“类型标识符类型标识符”必须必须声明为声明为void(无类型或称空类型无类型或称空类型)。void star()printf(*n);void message()printf(game over!n);8.4 函数的调用函数的调用一、函数调用的一般形式一、函数调用的一般形式 函数名(函
12、数名(实参列表实参列表)函函数数调调用用时时,要要求求实实参参与与形形参参个个数数相相等等,类类型型对对应应一一致致,实实参参与与形形参参按按顺顺序序一一一一对对应应传传递递数数据据,实实参参表表中中各各参参数数的的求求值值顺顺序序,C标标准准未未作作统统一一规规定定,Turbo C按按自自右右向向左左的的顺顺序求值。序求值。二、函数调用的方式二、函数调用的方式z函数调用作为一个语句函数调用作为一个语句 printstar();z函数作为表达式的一部分函数作为表达式的一部分c=2*max(a,b);z函数的值作为一个函数的参数函数的值作为一个函数的参数 m=max(a,max(b,c);pri
13、ntf(%d,max(a,b);三、对被调函数的说明三、对被调函数的说明 在一个函数中调用另一个函数,需要具备那在一个函数中调用另一个函数,需要具备那些条件:些条件:z1、被调用的函数必须已经存在。、被调用的函数必须已经存在。z2、使用系统预定义的函数(库函数),必须、使用系统预定义的函数(库函数),必须包含头文件,因为头文件中包含头文件,因为头文件中声明声明了库函数的了库函数的原型(函数名、返回值类型及形参类型称为原型(函数名、返回值类型及形参类型称为函数的原型)。函数的原型)。#include stdio.h#include“math.h”z3、如如果果使使用用用用户户自自己己定定义义的的
14、函函数数,而而且且主主调调函函数数与与被被调调函函数数在在同同一一文文件件中中,通通常常应应该该在在主调函数中对被调用的函数主调函数中对被调用的函数作一个声明作一个声明.例例8.2main()float add(float x,float y);/*对对add函数的声明函数的声明*/float a,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sum is%f,c);float add(float x,float y)/*add函数的定义函数的定义*/float z;z=x+y;return z;在在main的开头声明函数原型。的开头声明函数原型。函数定义和
15、函数声明的区别函数定义和函数声明的区别 定义:定义:确立函数的功能,包括指定函数名、确立函数的功能,包括指定函数名、函数值类型、形参及其类型、函数体等,是一函数值类型、形参及其类型、函数体等,是一个完整的、独立的函数单位。个完整的、独立的函数单位。声明:声明:函数声明称为函数原型函数声明称为函数原型,是对已定是对已定义的函数的返回值进行类型说明,只包括函数义的函数的返回值进行类型说明,只包括函数名、函数类型及一个空括弧,不包括形参和函名、函数类型及一个空括弧,不包括形参和函数体。数体。(但通常可给出形参相关信息,在但通常可给出形参相关信息,在这便这便于编译系统进行检错,以防止可能出现的错误于编
16、译系统进行检错,以防止可能出现的错误)函数声明的一般形式函数声明的一般形式(1)函数类型函数类型 函数名函数名(参数类型参数类型1,参数类型,参数类型2,););(2)函数类型函数类型 函数名函数名(参数类型参数类型1 参数名参数名1,参数,参数类型类型2 参数名参数名2,););例例float add(float x,float y);等价于:等价于:float add(float,float);函数原型与函数定义中的函数首部写法上应该函数原型与函数定义中的函数首部写法上应该一致,函数类型、函数名、参数个数、参数类一致,函数类型、函数名、参数个数、参数类型和参数顺序必须一样。型和参数顺序必须
17、一样。函数调用时:函数名、实参个数应和函数原型函数调用时:函数名、实参个数应和函数原型一致。实参类型必须于函数原型中的形参类型一致。实参类型必须于函数原型中的形参类型赋值兼容。赋值兼容。main()int a,b,c;scanf(%d,%d,&a,&b);c=max(a,b);printf(max is%dn,c);int max(int x,int y)int z;z=xy?x:y;return(z);1、返回值为整型、返回值为整型的函数。编译系的函数。编译系统会把第一次遇统会把第一次遇到的函数调用作到的函数调用作为函数的声明。为函数的声明。不需要函数声明的情况不需要函数声明的情况float
18、 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);2、被调用函数的定义出现在主调用函数之前、被调用函数的定义出现在主调用函数之前float add(float x,float y);main()float a,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sum is%f,c);float z;z=x+y;return z;3、在所有函数定义之前,文件的开头,已经、在所有函数定义之前,文件
19、的开头,已经作了函数声明。作了函数声明。8.5 函数的嵌套调用函数的嵌套调用z函函数数的的嵌嵌套套调调用用:在在一一个个函函数数的的函函数体内调用另一个函数。数体内调用另一个函数。scanf()main()printf()y()getchar()max()main()a()b()调用调用a()调用调用b()调用一个函数过程中又调用了另一个函数调用一个函数过程中又调用了另一个函数在函数的嵌套调用中,函数的执行采取在函数的嵌套调用中,函数的执行采取后调用后调用先返回先返回的原则。即最内层的函数调用最先返回的原则。即最内层的函数调用最先返回函数值,由内到外依次返回。函数值,由内到外依次返回。例例8.
20、3求解求解x3-5x2+16x-80=0的根的根解题步骤:解题步骤:1.取两个不同点取两个不同点x1,x2 如果如果f(x1)和和f(x2)符号相反,符号相反,则则x1,x2区间必有一个根,区间必有一个根,如果同号,则应改变如果同号,则应改变x1和和 x2,直至异号为止,直至异号为止2.连接连接f(x1)和和f(x2),交,交x轴于轴于 x点,则点,则x=x1*f(x2)-x2*f(x1)/f(x2)-f(x1)3.求求f(x)4.若若f(x)与与f(x1)同号,则同号,则(x,x2)有根,此时将有根,此时将x作为作为x1 若若f(x)与与f(x2)同号,则同号,则(x,x1)有根,此时将有根
21、,此时将x作为作为x25.重复重复24的步骤,直至的步骤,直至f(x)0)y1=y;x1=x;else x2=x;while(fabs(y)=0.0001);return(x);/*1./*1.从以上函数可知,所有函数均是独立的从以上函数可知,所有函数均是独立的*/*/*2./*2.所有函数均设为所有函数均设为 float*/float*/*3./*3.所有函数均在所有函数均在 main()main()之前定义之前定义*/*/main()float x1,x2,f1,f2,x;do printf(input x1,x2:n);scanf(%f,%f,&x1,&x2);f1=f(x1);f2=f
22、(x2);while(f1*f2=0);x=root(x1,x2);printf(A root of equation is%8.4f,x);main()调用函数调用函数root输出根输出根 x结束结束root函数函数xpoint函数函数调用函数调用函数xpoint调用函数调用函数ff函数函数8.6 函数的递归调用函数的递归调用z递递归归调调用用:一一个个函函数数的的函函数数体体直直接接或或间间接接调用该函数本身调用该函数本身.int f(int x)int y,z;z=f(z);/*直接调用该函数本身直接调用该函数本身*/return(2*z);有五个人坐在一起,求第有五个人坐在一起,求第5
23、个人多少岁。个人多少岁。第第5个人多少岁?个人多少岁?比第比第4个人大个人大2岁。岁。第第4个人多少岁?个人多少岁?比第比第3个人大个人大2岁。岁。第第3个人多少岁?个人多少岁?比第比第2个人大个人大2岁。岁。第第2个人多少岁?个人多少岁?比第比第1个人大个人大2岁。岁。第第1个人多少岁?个人多少岁?我我10岁。岁。表达为:表达为:age(5)=age(4)+2 age(4)=age(3)+2 age(3)=age(2)+2 age(2)=age(1)+2 age(1)=10;递归表达式递归表达式:例例8-4z求解过程求解过程:用一个函数用一个函数age()来求第来求第n个人多少岁。个人多少岁
24、。main()int age();/*声明函数原型声明函数原型*/printf(%dn,age(5);int age(int n)/*求第求第n个人多少岁个人多少岁*/int c;if(n=1)c=10;else c=age(n-1)+2;return c;age(5)=18age(4)=16age(3)=14 age(2)=12age(1)=10age函数 n=5age函数 n=4age函数 n=3age函数 n=2age函数 n=1mainage(5)输出age(5)c=age(4)+2c=10c=age(1)+2c=age(2)+2c=age(3)+2求求n的阶乘的阶乘例例8-5floa
25、t fac(int n)float f;if(n0)printf(n%cn,getone,putone);void hanoi(int n,char one,char two,char three)if(n=1)move(one,three);else hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three);main()int m;printf(Input the number of disks:);scanf(%d,&m);printf(The steps to moving%3d disks:n,m);hanoi(
26、m,A,B,C);ABC例例8-6从例题中可以看到,有些问题,采用递归的方法解决,从例题中可以看到,有些问题,采用递归的方法解决,会变得非常简单,且源程序也很简洁。会变得非常简单,且源程序也很简洁。一个问题要采用递归的方法解决时,要符合以下条件:一个问题要采用递归的方法解决时,要符合以下条件:1、可以把一个问题转化为一个新问题,而新问题的解、可以把一个问题转化为一个新问题,而新问题的解决方案仍与原问题相同,只是问题的规模不同。它们只决方案仍与原问题相同,只是问题的规模不同。它们只是有规律的递增或递减。是有规律的递增或递减。2、可以通过转化过程使问题得到解决。、可以通过转化过程使问题得到解决。3
27、、必须有一个明确的结束递归的条件。、必须有一个明确的结束递归的条件。8.7 数组作为函数参数数组作为函数参数 关于数组要点:关于数组要点:设数组:设数组:int a5z1、a0、a1、a2、a3、a4表示每一个表示每一个 元素元素 的值。的值。z2、数组名、数组名a表示该数组在内存的起始地址。表示该数组在内存的起始地址。z3、可以用地址运算符、可以用地址运算符&获得某个元素的地址。获得某个元素的地址。如如&a2获得元素获得元素a2的地址的地址.第一个元素第一个元素 a0的地址的地址&a0即为数组即为数组a的起始地址。的起始地址。z4、数组元素数组元素作为函数的参数时,采用作为函数的参数时,采用
28、“值传送值传送”即即单向传送,即把单向传送,即把元素的值元素的值传送给形式参数;传送给形式参数;数组名数组名作为函数参数时,采用作为函数参数时,采用“地址传送地址传送”,即把数组的,即把数组的起始地址传送给形式参数。起始地址传送给形式参数。1、数组元素作为函数的参数。、数组元素作为函数的参数。采用采用“值传送值传送”即单向传送,即把元素的值传即单向传送,即把元素的值传送给形式参数;送给形式参数;a和和b为有为有10个元素的整型数组个元素的整型数组比较两数组对应元素比较两数组对应元素变量变量n,m,k记录记录aibi,ai=bi,aik,认为数组认为数组ab 若若nk,认为数组认为数组ay)fl
29、ag=1;else if(xy)flag=-1;else flag=0;return (flag);#include main()int a10,b10,i,n=0,m=0,k=0;printf(Enter array a:n);for(i=0;i10;i+)scanf(%d,&ai);printf(Enter array b:n);for(i=0;i10;i+)scanf(%d,&bi);for(i=0;ibi%d timesnai=bi%d timesnaik)printf(array a is larger than array bn);else if(nk)printf(array a
30、 is smaller than array bn);else printf(array a is equal to array bn);2、数组名可作为函数参数、数组名可作为函数参数有一个一维数组有一个一维数组score,内放,内放10个学个学生成生成 绩,求平均成绩。绩,求平均成绩。float average(float array10)int i;float aver,sum=array0;for(i=1;i10;i+)sum=sum+arrayi;aver=sum/10;return(aver);例例8-8不起任何作用,编译不起任何作用,编译系统不对此大小作任系统不对此大小作任何检查。
31、何检查。main()float score10,aver;int i;printf(input 10 score:n);for(i=0;i10;i+)scanf(%f,&scorei);printf(n);aver=average(score);printf(average score is%5.2f,aver);数组元素与数组元素与 数组名作函数参数比较数组名作函数参数比较#include void swap2(int x,int y)int z;z=x;x=y;y=z;main()int a2=10,20;swap2(a0,a1);printf(a0=%dna1=%dn,a0,a1);值传
32、递值传递1020a调用前调用前a0a11020a调用调用a0a11020 xy2010 xy交换交换1020a返回返回1020a调用前调用前1020ax调用调用2010ax交换交换2010a返回返回#include void swap2(int x)int z;z=x0;x0=x1;x1=z;main()int a2=10,20;swap2(a);printf(a0=%dna1=%dn,a0,a1);地址传递地址传递float average(float array,int n)int i;float aver,sum=array0;for(i=1;in;i+)sum=sum+arrayi;a
33、ver=sum/n;return(aver);main()static float score_15=98.5,97,91.5,60,55;static float score_210=67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5;printf(the average of class A is%6.2fn,average(score_1,5);printf(the average of class B is%6.2fn,average(score_2,10);3、用多维数组名作函数参数、用多维数组名作函数参数例例8.9 有一个有一个3*4的矩阵,求所有元
34、素中的最大值。的矩阵,求所有元素中的最大值。max_value(int array 4)int i,j,k,max;max=array00;for(i=0;i3;i+)for(j=0;jmax)max=arrayij;return(max);main()int a34=1,3,5,7,2,4,6,8,15,17,34,12;printf(maxvalueis%dn,max_value(a);8.8 局部变量和全局变量局部变量和全局变量一、局部变量一、局部变量局局部部变变量量:在在函函数数内内部部定定义义的的变变量量,它它只只在在该该函函数范围内有效数范围内有效(可以使用可以使用),称为,称为“
35、局部变量局部变量”。float f1(int a)int b,c;main ()int m,n;a、b、c有效m、n有效main()int a,b;int c;c=a+b;c有效有效a、b有效有效关于局部变量的说明关于局部变量的说明1.主函数中定义的主函数中定义的变量也只在主函数变量也只在主函数中有效。中有效。2.不同函数中可以不同函数中可以使用相同名称的变使用相同名称的变量。量。3.形参也是局部变形参也是局部变量。量。4.复合语句中定义复合语句中定义的变量只在本复合的变量只在本复合语句中有效。语句中有效。二、全局变量二、全局变量全局变量全局变量:在任何:在任何函数之外函数之外定义的变量,定义
36、的变量,也也称为称为外部变量,外部变量,从定义它开始,在整个程序(所有从定义它开始,在整个程序(所有函数)内都是有效的函数)内都是有效的(或称为或称为“可见的可见的”,即可以,即可以使用使用)。int p=1,q=5;/*外部变量外部变量*/float f1(int a)/*定义函数定义函数f1*/int b,c;char c1,c2;/*外部变量外部变量*/char f2(int x,int y)/*定义函数定义函数f2*/int i,j;main ()/*主函数主函数*/int m,n;全局变全局变量量c1、c2的作的作用范围用范围全局变全局变量量 p、q的作的作用范围用范围1、全全局局变
37、变量量从从定定义义它它开开始始,在在整整个个程程序序中中均均可可以以使使用用。因因此此,对对于于多多个个函函数数需需要要使使用用的的共共同同变变量量,设计为全局变量。设计为全局变量。2、建议少用全局变量。、建议少用全局变量。因为:因为:全全局局变变量量在在整整个个程程序序运运行行过过程程中中都都占占内内存存;局局部部变变量量仅仅在在定定义义局局部部变变量量的的函函数数被被执执行行时时才才占占内内存存,函数执行完释放所占内存。函数执行完释放所占内存。全局变量使各函数互相关联,结构性差。全局变量使各函数互相关联,结构性差。降降低低程程序序可可读读性性。因因为为全全局局变变量量的的值值随随时时可可能
38、能被被其其他他位位置置的的程程序序修修改改,不不便便于于阅阅读读,使使程程序序容容易易出错。出错。3.在同一源文件中,若外部变量与局部变量同名,在同一源文件中,若外部变量与局部变量同名,则在局部变量的作用域内,外部变量不起作用。则在局部变量的作用域内,外部变量不起作用。全局变量作为公共变量全局变量作为公共变量例例8.10 有一个数组,内放有一个数组,内放10个学生成绩,写一个个学生成绩,写一个函数,求出平均分、最高分、最低分。函数,求出平均分、最高分、最低分。把平均分设计为函数把平均分设计为函数average的返回值,最高分的返回值,最高分max、最低分、最低分min在函数在函数average
39、和主函数和主函数main中均需要中均需要使用,设计为全局变量。使用,设计为全局变量。float Max,Min;float average(float array,int n)int i;float sum=array0;Max=Min=array0;for(i=1;iMax)Max=arrayi;else if(arrayiMin)Min=arrayi;sum+=arrayi;return(sum/n);main()int i;float ave,score10;for(i=0;ib?a:b;return(c);main()int a=8;printf(max=%d,max(a,b);运行结
40、果:运行结果:max=8例、写出下面程序的执行结果。例、写出下面程序的执行结果。int k=3;main()int k=7;printf(k=%dn,k);int k=11;printf(k=%dn,k);k+=1;printf(k=%dn,k);printf(k=%dn,k);printf(k=%dn,k);k=7k=11k=12k=12k=78.9 动态存储变量和静态存储变量动态存储变量和静态存储变量一、变量的存储类别一、变量的存储类别z 从变量的从变量的作用域作用域(可见性)可见性)看,变量分为:看,变量分为:全局变量全局变量 局部变量局部变量静态静态外部变量外部变量(本文件引用本文件引
41、用)外部变量外部变量(允许其它文件引用允许其它文件引用)自动变量自动变量(动态局部动态局部变量变量)(本函数内有效本函数内有效)静态局部变量静态局部变量(离开函数离开函数,值仍保持值仍保持)寄存器变量寄存器变量(离开函数离开函数,值就消失值就消失)z从变量从变量存在的时间(生存期)存在的时间(生存期)上看上看,变量分为变量分为:静态存储变量静态存储变量:程序运行期间分配:程序运行期间分配固定的内存固定的内存空间。空间。动态存储变量动态存储变量:程序运行期间:程序运行期间不固定分配内存不固定分配内存空间空间,仅在需要时分配,不需要时就仅在需要时分配,不需要时就释放释放。静态存储区静态存储区 动态
42、存储区动态存储区 计算机内存一方面供操作系统使用(称为系统区)计算机内存一方面供操作系统使用(称为系统区),另方面供用户程序使用(称为用户区,另方面供用户程序使用(称为用户区)静态局部变量静态局部变量外部变量(全局变量)外部变量(全局变量)自动局部变量自动局部变量寄存器变量寄存器变量形式参数形式参数z变量的变量的属性属性:数据类型和数据的存储类别数据类型和数据的存储类别.z变变量量的的存存储储类类别别:指指数数据据在在内内存存中中的的存存储方法,有两大类:储方法,有两大类:静态存储静态存储 动态存储动态存储 具体包括四种:具体包括四种:自动的(自动的(auto)寄存器的(寄存器的(regist
43、er)静态的(静态的(static)外部的(外部的(extern)二、二、auto变量变量1、局部变量自动的(局部变量自动的(autoauto)存储方式)存储方式。函函数数的的局局部部变变量量,不不专专门门说说明明为为静静态态变变量量,都都是是动动态态分分配配存存储储空空间间,存存储储在在动动态态存存储储区区。对对它它们们的的分分配配和和释释放放是是由由编编译译系系统统自自动动处处理理的的,因因此此,称称为为自动变量。自动变量。z不不作作专专门门说说明明的的局局部部变变量量,均均是是自自动动变变量量。也也可可以以用关键字用关键字auto作出明确说明。作出明确说明。例、例、int f(int a
44、)auto int b,c=3;/*自动变量自动变量*/int x,y=2;/*未作专门说明,隐含为自动变量未作专门说明,隐含为自动变量*/三、三、用用staticstatic声明局部变量声明局部变量 在在函函数数调调用用结结束束后后,其其所所占占内内存存空空间间不不被被释释放放,其其值值保保留留原原值值.则则应应该该指指定定该该局局部部变变量量为为“局局部部静态变量静态变量”.z 用关键字用关键字static作专门说明。作专门说明。z在在定定义义静静态态局局部部变变量量时时不不赋赋初初值值的的话话,系系统统自自动赋值为动赋值为0或空字符(对字符变量)。或空字符(对字符变量)。int f(in
45、t a)auto int b=0;/*自动变量自动变量*/static int c=3;/*静态局部变量静态局部变量*/b=b+1;c=c+1;return(a+b+c);main()int a=2,i;for(i=0;i3;i+);printf(%d,f(a);输出结果是:输出结果是:7 8 9调用函数调用函数f 调用时初值调用时初值 调用结束时的值调用结束时的值 b自动自动 c静态静态 b自动自动 c静态静态 a+b+c 第第1次次 0 3 1 4 7 第第2次次 0 4 1 5 8 第第3次次 0 5 1 6 9 例例8.12求求1到到5的阶乘的阶乘int fac(int n)stati
46、c int f=1;f=f*n;return(f);main()int i;for(i=1;iy?x:y;return(z);main()extern A,B;printf(%dn,max(A,B);int A=13,B=-8;外部变量定义外部变量定义用用extern扩展外部变扩展外部变量的量的(2 2)对于由几个文件组成的)对于由几个文件组成的C C程序,当一个源文件程序,当一个源文件A A要引用另一个源文件要引用另一个源文件B B中的全局变量时,要用中的全局变量时,要用externextern将该全局变量的作用域扩展到源文件将该全局变量的作用域扩展到源文件B B中。中。/*file1.c*
47、/int a;main()int power(int);int b=3,c,d,m;printf(enter the number a and its power:n);scanf(%d,%d,&a,&m);c=a*b;printf(%d*%d=%dn,a,b,c);d=power(m);printf(%d*%d=%d,a,m,d);/*file2.c*/extern int a;power(int n)int i,y=1;for(i=1;i=n;i+)y*=a;return(y);给定给定b,输入,输入a、m,求求a*b和和am。(二)全局变量使用二)全局变量使用static修饰符,其作用域
48、只在它修饰符,其作用域只在它定义的源程序中。定义的源程序中。(三三)函数外全局变量只能定义函数外全局变量只能定义1次次!静态静态动态动态存储方式存储方式程序整个运行期间程序整个运行期间函数调用开始至结束函数调用开始至结束生存期生存期编译时赋初值,编译时赋初值,只赋一次只赋一次每次函数调用时每次函数调用时赋初值赋初值自动赋初值自动赋初值0 0或空字符或空字符不确定不确定未赋初值未赋初值静态存储区静态存储区动态区动态区存储区存储区寄存器寄存器局部变量局部变量外部变量外部变量作用域作用域定义变量的函数或复合语句内定义变量的函数或复合语句内本文件本文件其它文件其它文件registerregister
49、局部局部staticstaticautoauto外部外部staticstatic外部外部存储类别存储类别存储类别小结存储类别小结/*file1.c*/int a;main()int power(int);int b=3,c,d,m;printf(enter the number a and its power:n);scanf(%d,%d,&a,&m);c=a*b;printf(%d*%d=%dn,a,b,c);d=power(m);printf(%d*%d=%d,a,m,d);/*file2.c*/extern int a;power(int n)int i,y=1;for(i=1;i=n;i+)y*=a;return(y);运行一个多文件程序z在集成环境在集成环境tc20中中,建立工程管理文件建立工程管理文件example.prj:file1.c file2.c编译运行编译运行example.prjfile1.c file1.objfile2.c file2.objexample.exe编译编译编译编译连接连接不建立工程管理文件不建立工程管理文件example.prj,把把file1.c改为改为:#include“file2.c”int a;main()