第七章 函数教学课件.pptx

上传人:春哥&#****71; 文档编号:11352441 上传时间:2022-04-18 格式:PPTX 页数:83 大小:2.92MB
返回 下载 相关 举报
第七章 函数教学课件.pptx_第1页
第1页 / 共83页
第七章 函数教学课件.pptx_第2页
第2页 / 共83页
点击查看更多>>
资源描述

《第七章 函数教学课件.pptx》由会员分享,可在线阅读,更多相关《第七章 函数教学课件.pptx(83页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、第7章 函数目录CONTENTS函数的概念与分类7.1函数的定义与函数的返回值7.2函数的调用7.3函数的嵌套调用和递归调用7.4数组作函数参数7.5变量的作用域与存储类别7.6编译预处理7.7 函数的概念与分类7.1 函数的概念函数的分类函数是形式上独立、功能上完整的程序段(块)。源程序是由函数组成的。函数是源程序的基本模块,通过对函数模块的调用实现特定的功能。语言不仅提供了极为丰富的库函数,而且还允许用户自己定义的函数。用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。一个C程序可由一个主函数和若干个其它函数构成,但必须至少有一个主函数。函数的概念函数的概念01函

2、数的分类函数的分类02函数定义角度函数定义角度用户自定义函数用户自定义函数库函数库函数函数功能角度函数功能角度无返回值函数无返回值函数有返回值函数有返回值函数数据传送角度数据传送角度有参函数有参函数无参函数无参函数函数的定义与函数的返回值7.2 函数的定义函数的参数和返回值函数的定义函数的定义011、无参、无参函数的定义函数的定义定义格式:定义格式:类型说明符类型说明符 函数函数名名() 函数体函数体 说明:说明:类型说明符:类型说明符:该函数值的类型,即函数返回值的该函数值的类型,即函数返回值的类型。若函数类型。若函数无返无返回值,函数类型用回值,函数类型用void。函数名:函数名:函数的名

3、字。取名规则遵循标识符的规则,函数的名字。取名规则遵循标识符的规则,后面必须有不后面必须有不带参数带参数的一对圆括号。的一对圆括号。函数体:函数体:完成该函数功能的一些说明完成该函数功能的一些说明部分和语句部分和语句序列。序列。2、有参、有参函数的定义函数的定义定义格式定义格式类型说明符类型说明符 函数名函数名(形式参数表列形式参数表列) 函数体函数体 形式参数形式参数(简称形参)可以是各种类型的变量,各参数之间用逗号(简称形参)可以是各种类型的变量,各参数之间用逗号间隔,必须在形式参数表中给出形参的类型说明。在函数调用时,主调函间隔,必须在形式参数表中给出形参的类型说明。在函数调用时,主调函

4、数将赋予这些形式参数以实际值。数将赋予这些形式参数以实际值。对于对于有参函数,函数的参数是主调函数和被调用函数之间数据传递有参函数,函数的参数是主调函数和被调用函数之间数据传递的通道。参数可分为形式参数(的通道。参数可分为形式参数(形参形参)和实际参数()和实际参数(实参实参)两种。)两种。 如果在定义函数时没有指定函数类型,系统会隐含指定函数类型为如果在定义函数时没有指定函数类型,系统会隐含指定函数类型为int型型#include int min(int x, int y)if (xy) return y; else return x;int main() int min(int x,int

5、 y); /* 函数声明函数声明 */ int a,b,c; printf(input two numbers:n); scanf(%d%d,&a,&b); c=min(a,b); /* 函数调用函数调用 */ printf(minmum=%d,c); return 0; 例例 从键盘输入两个整数,输出其较小的数。从键盘输入两个整数,输出其较小的数。u 在定义函数时,可以没有函数体,但花括号在定义函数时,可以没有函数体,但花括号必须有,这样的函数称必须有,这样的函数称为为空空函数函数。u 在语言中,所有的函数定义,包括主函数在语言中,所有的函数定义,包括主函数main在内,都是平行的。在内,都

6、是平行的。也就是说,在一个函数的函数体内,不能再定义另一个函数,即也就是说,在一个函数的函数体内,不能再定义另一个函数,即不能不能嵌套嵌套定义定义。u 一一个源程序必须有,也只能有一个主函数个源程序必须有,也只能有一个主函数main。函数的参数函数的参数02函数的参数分为形式参数(简称形参)和实际参数(简称实参)两种。形参出现在函数定义中,在整个函数体内都可以使用,离开该函数则不能使用。实参出现在主调函数中,进入被调函数后,实参变量也不能使用。形参和实参的功能是作数据传送。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。函数的形参和实参具有以下特点:

7、(1)只有当函数被调用时,系统才给形参变量分配内存单元,在调用结束时,所分配的内存单元就被释放。(2)实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。(3)实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。函数的参数函数的参数02函数的返回值函数的返回值函数函数的数据类型就是函数返回值的类型,称为的数据类型就是函数返回值的类型,称为函数类型函数类型。函数函数的返回值通过函数中的返回值通过函数中的的return语句语句将将被调用函数中的一个确被调用函数中的一个确定的值带回到主调函数中去。定的

8、值带回到主调函数中去。 return一般一般形式:形式:return(表达式表达式);return 表达式表达式;return ;03在在定义函数定义函数时时应当应当指定指定函数值的函数值的类型类型。凡凡不加类型说明的函数,一不加类型说明的函数,一律自动按整型处理律自动按整型处理。如果如果函数值的类型和函数值的类型和return语句中表达式的值不一致,则以函数类语句中表达式的值不一致,则以函数类型为准型为准。不不返回函数值的函数,可以明确定义为返回函数值的函数,可以明确定义为“空类型空类型”,类型说明符为,类型说明符为“void”。如果如果被调用函数没有被调用函数没有return语句,则函数将

9、带回有关不确定的值。语句,则函数将带回有关不确定的值。 函数的参数函数的参数02 函数的调用7.3 函数的声明和函数调用格式函数的参数传递main() int a; f1(a); f1(int x) 调用调用返回返回 当在一个函数中调用另一个函数,程序控制就从主调函数中的函数调当在一个函数中调用另一个函数,程序控制就从主调函数中的函数调用语句转移到被调函数,执行被调函数体中的语句序列,在执行完函数体用语句转移到被调函数,执行被调函数体中的语句序列,在执行完函数体中所有的语句,遇到中所有的语句,遇到return语句或函数体的最后一个语句后的右花括号语句或函数体的最后一个语句后的右花括号“”时,自

10、动返回到主调函数的函数调用语句并继续往下执行。时,自动返回到主调函数的函数调用语句并继续往下执行。 下面来看怎下面来看怎么调用么调用函数声明的函数声明的一般格式一般格式: 类型说明符类型说明符 函数名函数名(形式参数表列形式参数表列);函数函数的声明的声明01说明:u在函数声明时,重要的是在函数声明时,重要的是形参类型形参类型和和形参个数形参个数,形参名并不重要。形参名并不重要。 u在以下情况下,可以省去对被调用函数在以下情况下,可以省去对被调用函数的声明的声明当被调用函数的定义出现在调用函数之前时。当被调用函数的定义出现在调用函数之前时。函数函数的返回值是整型或字符型,可以不必的返回值是整型

11、或字符型,可以不必进行进行声明声明。如果如果在所有函数定义之前,在函数外部预先对各个函数进行在所有函数定义之前,在函数外部预先对各个函数进行了了声明声明,则在调用函数中可缺省对被调用函数则在调用函数中可缺省对被调用函数的的声明声明。 函数调用的函数调用的一般格式一般格式函数名函数名(实际参数表实际参数表) 一般格式:一般格式:02调用调用函数时,函数名称必须与具有该功能的自定义函数名称完全一函数时,函数名称必须与具有该功能的自定义函数名称完全一致。如果是调用无参函数则实参表列可以没有,但括弧不能省略。致。如果是调用无参函数则实参表列可以没有,但括弧不能省略。 实参实参的个数、类型和顺序,应该与

12、被调用函数所要求的参数个数、的个数、类型和顺序,应该与被调用函数所要求的参数个数、类型和顺序一致,才能正确地进行数据传递类型和顺序一致,才能正确地进行数据传递 函数调用的方式函数调用的方式函数语句函数语句例如:例如:printf(“%d”,x);只进行某些操作而不返回函数值只进行某些操作而不返回函数值函数表达式函数表达式例如:例如:m=5*min(a,b);函数作为表达式的一项出现在表达式中函数作为表达式的一项出现在表达式中函数实参函数实参例如:例如:n=min(a,min(b,c);函数作为另一个函数调用的实际参数出现函数作为另一个函数调用的实际参数出现03例例:函数的调用:函数的调用#in

13、clude int main() int fun(int x,int y); /*函数声明*/ int i=2,j=6,s; s=f(i,j); /*函数调用*/ printf(%d,s); return 0;int fun(int x,int y) /*函数定义*/ int z; z =x+y; return z;函数的参数函数的参数传递传递在在调用函数时,大多数情况下,主调函数和被调用函数之间有调用函数时,大多数情况下,主调函数和被调用函数之间有数据数据传递传递关系关系。形参形参和实参的功能是作数据传送。发生函数调用时,主调函数把实和实参的功能是作数据传送。发生函数调用时,主调函数把实参的

14、值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。在在C语言中,实参向形参传送数据的方式是语言中,实参向形参传送数据的方式是“值传递值传递”。函数间形。函数间形参与实参的值的传递过程就是将实参的值拷贝一份给形参变量。参与实参的值的传递过程就是将实参的值拷贝一份给形参变量。其其优点优点在于:被调用的函数不可能改变调用函数中变量的值在于:被调用的函数不可能改变调用函数中变量的值。 04例:调用例:调用函数时的数据传递。函数时的数据传递。#include int main() void swap(int,int); int a

15、,b; printf(请输入两个整数a,b:); scanf(%d%d,&a,&b); swap(a,b); printf(a=%d,b=%dn,a,b); return 0;void swap(int x,int y) int temp; temp=x;x=y;y=temp; printf(x=%d,y=%dn,x,y); 函数的嵌套调用和递归调用7.4 函数的嵌套调用函数的递归调用函数的嵌套调用函数的嵌套调用在在C语言中,不能将函数定义放在另一个函数的函数体中,但允许在语言中,不能将函数定义放在另一个函数的函数体中,但允许在调用一个函数的过程中调用另一个函数。这称为函数的嵌套调用。调用一个

16、函数的过程中调用另一个函数。这称为函数的嵌套调用。01main函数函数 : c=f1(a); : f1(int s)函数函数 : d=f2(x,y); :f2(int x,int y)函数函数 : :例:用例:用弦弦截截法法求方程求方程x3-5x2+16x-80=0的根。的根。 用弦切法求方程用弦切法求方程f(x)=0的根的算法为:的根的算法为:s1:在函数的定义域内取两点:在函数的定义域内取两点x1,x2,使使f(x1)*f(x2)0;s2:求两点:求两点(x1,f(x1) , (x2,f(x2)的连线与的连线与x轴的交点轴的交点x; x=(x1*f(x2)-x2*f(x1)/(f(x2)-

17、f(x1)s3:判断:判断f(x)e(e为给定的很小的一个数为给定的很小的一个数),若成立若成立,转转s6;否则否则转转s4;s4:判断:判断f(x)*f(x1)0,若成立,若成立,x2=x;否则否则 x1=x; s5:转:转s2;s6:输出:输出x,它即为所求的根。,它即为所求的根。函数的嵌套调用函数的嵌套调用01#include #include double f(double x) double y; y=x*x*x-5*x*x+16*x-80; return y;double xpoint(double x1,double x2) double z; z=(x1*f(x2)-x2*f(

18、x1)/(f(x2)-f(x1); return z;函数的嵌套调用函数的嵌套调用01函数的嵌套调用函数的嵌套调用01double root(double x1,double x2) double 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(fabs(y)=0.00001); return x;main()root()xpoint()f()int main() double x1,x2,f1,f2,x; do printf(Input x1,x2:n); scanf(%l

19、f,%lf,&x1,&x2); f1=f(x1); f2=f(x2); while(f1*f2=0); x=root(x1,x2); printf(A root of equation is %8.4lfn,x); return 0; 函数的嵌套调用函数的嵌套调用01函数的递归调用函数的递归调用概念:概念:函数在它的函数体内直接或间接地调用它自身函数在它的函数体内直接或间接地调用它自身 优点优点:可使程序简洁,提高程序的可读性。:可使程序简洁,提高程序的可读性。缺点缺点:递归:递归调用会增加存储空间和调用会增加存储空间和执行时间执行时间上的开销。上的开销。 02funa() funa(); f

20、unb() func(); func() funb(); 直接递归调用直接递归调用间接递归调用间接递归调用 一个问题要采用递归方法来解决时必须符合以下三个条件:一个问题要采用递归方法来解决时必须符合以下三个条件:(1)能将问题转化为一个新的问题,而这个新问题的解决方法与原问题)能将问题转化为一个新的问题,而这个新问题的解决方法与原问题的解法相同,它们只是有规律的递增或递减。的解法相同,它们只是有规律的递增或递减。(2)通过转化过程使问题得到解决。)通过转化过程使问题得到解决。(3)要有一个明确的结束递归的条件。)要有一个明确的结束递归的条件。 递归程序的执行过程可分为递归程序的执行过程可分为递

21、推递推和和回归回归两个阶段。两个阶段。在在递推阶段递推阶段,把较复杂的问题(规模为,把较复杂的问题(规模为n)的求解推到比原问题简单一些)的求解推到比原问题简单一些的问题(规模小于的问题(规模小于n)的求解。在)的求解。在回归阶段回归阶段,当获得最简单情况的解后,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解。逐级返回,依次得到稍复杂问题的解。函数的递归调用函数的递归调用02例例:编写编写一个递归函数,求一个递归函数,求n的阶乘值的阶乘值n!0)1(01)(nnfactnnnfact显然显然, 当当n0时,时,fact(n)是建立在是建立在fact(n-1)的基础上。由于的基础上。由

22、于求解求解fact(n-1)的过程与求解的过程与求解fact(n)的过程完全相同,只是具体的过程完全相同,只是具体实参不同,因而只需借助递归机制进行自身调用即可。于是实参不同,因而只需借助递归机制进行自身调用即可。于是求求n的阶乘值的阶乘值fact(n)的具体实现为:的具体实现为:若用若用fact(n)表示表示n的阶乘值,根据阶乘的数学定义可知:的阶乘值,根据阶乘的数学定义可知:long fact(int n) long m; if (n = 0) m=1; elsem=n*fact(n-1); return(m);数组作函数参数7.5 数组名作函数参数数组元素作函数参数二维数组作函数参数 数

23、组元素作函数的参数与普通变量作函数的参数本质相同。数组数组元素作函数的参数与普通变量作函数的参数本质相同。数组元素作函数实参时,仅仅是将其代表的值作为实参处理。元素作函数实参时,仅仅是将其代表的值作为实参处理。 数组中元素作为函数的实参,与简单变量作为实参一样,结合的数组中元素作为函数的实参,与简单变量作为实参一样,结合的方式是单向的值传递。方式是单向的值传递。数组元素作函数的参数数组元素作函数的参数01例例:求求数组中的最大元素。数组中的最大元素。#include float max(float x,float y) if(xy) return x; else return y; int m

24、ain() int k; float m,a=12.34,123,-23.45,67.89,43,79,68,32.89,-34.23,10; m=a0; /*假设第一个元素是最大值*/ for(k=1;k10;k+) /*循环9次*/ m=max(m,ak); /*调用max函数,实参m和ak给形参x,y*/ printf( %5.2fn,m); /*输出m的值 */ return 0;数组元素作函数的参数数组元素作函数的参数01 用数组名作函数的参数可以解决函数只能有一个返回用数组名作函数的参数可以解决函数只能有一个返回值的问题。值的问题。数数组名代表数组的首地址,在数组名作为函数的参数时

25、,形参和实参都应组名代表数组的首地址,在数组名作为函数的参数时,形参和实参都应该是数组名。该是数组名。 在函数调用时,实参给形参传递的数据是实参数组的首地址,即实在函数调用时,实参给形参传递的数据是实参数组的首地址,即实参数组和形参数组完全等同,是存放在同一存储空间的同一个数组,形参数组和形参数组完全等同,是存放在同一存储空间的同一个数组,形参数组和实参数组共享存储单元。如果在函数调用过程中形参数组的内参数组和实参数组共享存储单元。如果在函数调用过程中形参数组的内容被修改了,实际上也是修改了实参数组的内容。容被修改了,实际上也是修改了实参数组的内容。数组名作函数参数数组名作函数参数02例:求例

26、:求数组中的最大元素。数组中的最大元素。#include void inputdata(int a,int n) int i; for(i=0;in;i+)scanf(%d,&ai);int max(int a,int n) int i,m; m=a0; for(i=1;in;i+) if(mai) m=ai; return m;int main() int array10; inputdata(array,10); printf( “最大值为:%dn,max(array,10); return 0;数组名作函数参数数组名作函数参数02形参数组与实参数组之间的结合要注意以下几点形参数组与实参数

27、组之间的结合要注意以下几点:1. 调用函数与被调用函数中分别定义数组,其数组名可以不同,调用函数与被调用函数中分别定义数组,其数组名可以不同,但类型必须一致。但类型必须一致。2. 形参数组与实参数组的结合是采用地址结合的,从而可以实现形参数组与实参数组的结合是采用地址结合的,从而可以实现数据的双向传递。在被调用函数中改变了形参数组元素的值,数据的双向传递。在被调用函数中改变了形参数组元素的值,实际上就改变了实参数组元素的值。实际上就改变了实参数组元素的值。3. 数数组组作作形参形参时,时,形参数组形参数组可以可以不不指定一维数指定一维数组的组的长度长度。数组名作函数参数数组名作函数参数02 多

28、维数组名也可以作为函数的实参和形参。在定义函数时,对形多维数组名也可以作为函数的实参和形参。在定义函数时,对形参数组的说明可以指定每一维的大小,也可以省略第一维的大小。但参数组的说明可以指定每一维的大小,也可以省略第一维的大小。但是不能把多维数组的第二维及其他高维的大小说明省略。因为从实参是不能把多维数组的第二维及其他高维的大小说明省略。因为从实参传来的是数组起始地址,如果在形参中不说明列数,则系统无法决定传来的是数组起始地址,如果在形参中不说明列数,则系统无法决定应为多少行多少列,也就无法确定数组元素在内存中的位置。应为多少行多少列,也就无法确定数组元素在内存中的位置。二维数组作为函数参数二

29、维数组作为函数参数03例:利用例:利用函数求两个矩阵的和矩阵。函数求两个矩阵的和矩阵。#include #define M 3#define N 3void inputdata(int aN,int m) int i,j; for(i=0;im;i+) for(j=0;jN;j+) scanf(%d,&aij);自定义函数:用于输入二维数组作为函数参数二维数组作为函数参数03void outputdata(int aN,int m) int i,j; for(i=0;im;i+) for(j=0;jN;j+)printf(%5d,aij); printf(n);void sum(int aN,

30、int bN,int cN,int m)int i,j;for(i=0;im;i+)for(j=0;jN;j+)cij=aij+bij;自定义函数:用于输出自定义函数:用于求和二维数组作为函数参数二维数组作为函数参数03int main() int matrix1MN,matrix2MN,matrix3MN; inputdata(matrix1,M); inputdata(matrix2,M); sum(matrix1,matrix2,matrix3,M); outputdata(matrix3,M); return 0;主函数二维数组作为函数参数二维数组作为函数参数03参数传递小结参数传递小

31、结:实实 参参形形 参参传递数据传递数据基本变量基本变量常常 数数表表 达达 式式数组元素数组元素基本变量基本变量传传 值值数组名数组名数组数组传传 址址变量的作用域与存储类别7.6 变量的作用域变量的存储类别局部变量与全局变量局部变量与全局变量 变量的作用域是指变量的可见范围或可使用的有效范围。变量的变量的作用域是指变量的可见范围或可使用的有效范围。变量的作用域可为一个函数,也可为整个程序。作用域可为一个函数,也可为整个程序。 C语言中变量说明的方式不同,其作用域也不同。语言中变量说明的方式不同,其作用域也不同。C语言中的变量,语言中的变量,按作用域范围可分为两种:局部变量和全局变量。按作用

32、域范围可分为两种:局部变量和全局变量。1、局部变量、局部变量 在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,在一个函数内部定义的变量是内部变量,它只在本函数范围内有效,即其作用域是有限的、局部的,称为局部变量即其作用域是有限的、局部的,称为局部变量。说明:说明: 不同不同函数中可以使用相同名字的变量,它们代表不同的对象,互不函数中可以使用相同名字的变量,它们代表不同的对象,互不干扰。干扰。 函数函数的形参也是局部变量。的形参也是局部变量。 在在一个函数内部,可以在复合语句中定义变量,这些变量只在本复一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句内有效,这种复合语句

33、也称为合语句内有效,这种复合语句也称为“分程序分程序”或或“程序块程序块”。 01例:例:float f1(int a) int b,c; :char f2(int x,int y) int i,j,b; :void main() int m,n,j; :函数函数f1a,b,c 有效有效函数函数f2x,y,i,j,b 有效有效main函数函数m,n,j 有效有效int f(float x) double y; : double z; : :x,y的作用的作用域域z的作用的作用域域例:局部变量应用举例例:局部变量应用举例#includeint main() int a=1,b=2,c=3; pr

34、intf(1- a=%d,b=%d,c=%d,a,b,c); int a,b,c; a=10,b=20,c=30; printf(2- a=%d,b=%d,c=%d,a,b,c); printf(3- a=%d,b=%d,c=%d,a,b,c); return 0;局部变量与全局变量局部变量与全局变量 01 2、全局变量全局变量 在函数外面定义的变量称为全局变量在函数外面定义的变量称为全局变量(外部变量外部变量)。全局变量可以。全局变量可以被本文件中的其他函数所共有。其作用域为从定义处开始至本文件的结被本文件中的其他函数所共有。其作用域为从定义处开始至本文件的结束。束。 在一个函数内,可以使用

35、本函数中的局部变量,又可以使用有效的在一个函数内,可以使用本函数中的局部变量,又可以使用有效的全局变量。全局变量。说明:说明: 全局变量全局变量的作用:增加函数间数据联系的渠道。由于同一文件的所的作用:增加函数间数据联系的渠道。由于同一文件的所有函数都可以引用全局变量的值,因此如果在一个函数中改变了全有函数都可以引用全局变量的值,因此如果在一个函数中改变了全局变量的值,就能影响到其他函数,相当于各函数间有直接的传递局变量的值,就能影响到其他函数,相当于各函数间有直接的传递通道。用全局变量可以从一个函数中返回多个值通道。用全局变量可以从一个函数中返回多个值。例例:输入:输入4个数,编一个函数求这

36、些数的平均值,最大数、最个数,编一个函数求这些数的平均值,最大数、最小数小数。#include float max=0.0 , min=0.0;float average(float a,float b,float c,float d);int main() float x1,x2,x3,x4,ave; scanf(%f,%f,%f,%f,&x1,&x2,&x3,&x4); ave=average(x1,x2,x3,x4); printf(Max=%f,Min=%f,Ave=%fn,max,min,ave); return 0;float average(float a,float b,flo

37、at c,float d) float ave; max=a; min=a; if(maxb) max=b; if(maxc) max=c; if(maxb) min=b; if(minc) min=c; if(mind) min=d; ave=(x1+x2+x3+x4)/4; return ave;局部变量与全局变量局部变量与全局变量 01 若若文件中的某一函数想引用定义在后面的全局变量,则应在该函数中文件中的某一函数想引用定义在后面的全局变量,则应在该函数中用关键字用关键字extern作作“外部变量说明外部变量说明”,表示该变量在函数的外部定义,表示该变量在函数的外部定义 在函数内部可以使

38、用它们在函数内部可以使用它们。 #include int max(int x,int y) return xy?x:y;int main() extern int a,b; printf(%dn,max(a,b); return 0;int a=13,b=8; 如果如果在同一个文件中,全局变量与局部变量同名,则在局部变量的作在同一个文件中,全局变量与局部变量同名,则在局部变量的作用范围内,全局变量不用范围内,全局变量不起作用起作用。例:#include int a=13,b=8;int max(int x,int y) return xy?x:y;int main() int a; a=34;

39、 printf(%dn,max(a,b); return 0;从从变量的作用域变量的作用域(即从空间即从空间)角度来分,可分为局部变量和全局变量。角度来分,可分为局部变量和全局变量。从从变量值存在的时间变量值存在的时间(即生存期即生存期)角度来分,可分为静态存储变量和角度来分,可分为静态存储变量和动态存储变量。动态存储变量。静态静态存储方式是指在程序的运行期间分配固定的存储空间的方式存储方式是指在程序的运行期间分配固定的存储空间的方式。动态动态存储方式则是在程序运行期间根据需要进行动态的分配存储空存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式间的方式。在在C语言中每一个变量有两

40、个属性:数据类型和数据的存储类别。语言中每一个变量有两个属性:数据类型和数据的存储类别。存储类别是指数据在内存中存储的方式。存储方式可分为两大类:静态存储类别是指数据在内存中存储的方式。存储方式可分为两大类:静态存储类和动态存储类。具体包括四种:自动的存储类和动态存储类。具体包括四种:自动的(auto)、静态的、静态的(static)、寄、寄存器的存器的(register)、外部的、外部的(extern)。变量的存储类别变量的存储类别021、自动存储变量、自动存储变量自动存储变量是指这样一种变量,当程序模块执行时,系统自动为自动存储变量是指这样一种变量,当程序模块执行时,系统自动为其分配存储空

41、间,变量的值也存在,当程序模块执行完毕后,其值和存其分配存储空间,变量的值也存在,当程序模块执行完毕后,其值和存储空间也随之消失。储空间也随之消失。 自动存储变量的定义格式为:自动存储变量的定义格式为: auto 类型说明符类型说明符 变量名变量名 =初值表达式初值表达式,. ;变量的存储类别变量的存储类别02在一般情况下,关键字在一般情况下,关键字auto可以省略。自动存储变量必须定义在函可以省略。自动存储变量必须定义在函数体内,或为函数的形参。数体内,或为函数的形参。性质:性质:1)作用域的有限性。)作用域的有限性。自动存储变量自动存储变量 是局部变量,其作用域为变量所在的是局部变量,其作

42、用域为变量所在的函数或变量所在的分程序。函数或变量所在的分程序。2)生存期的短暂性。)生存期的短暂性。只有当程序模块执行时,本模块中的自动存储变量只有当程序模块执行时,本模块中的自动存储变量的值才存在,退出此模块时,本模块中的自动存储变量的空间被释放的值才存在,退出此模块时,本模块中的自动存储变量的空间被释放。3)可见性与存在性的一致性。)可见性与存在性的一致性。4)独立性独立性。5)未赋初值前的值无意义。)未赋初值前的值无意义。变量的存储类别变量的存储类别022、寄存器存储变量、寄存器存储变量 寄存器存储变量具有与自动存储变量完全相同的性质。当将一个变量寄存器存储变量具有与自动存储变量完全相

43、同的性质。当将一个变量定义为寄存器存储类别时,系统将它存放在定义为寄存器存储类别时,系统将它存放在CPU中的一个寄存器中。通常中的一个寄存器中。通常将使用频率较高的变量定义为寄存器存储变量。寄存器存储变量的定义格将使用频率较高的变量定义为寄存器存储变量。寄存器存储变量的定义格式式为为: register 类型说明符类型说明符 变量变量名名。#include int main( ) register int x=1; inner( ); printf(%dn,x); return 0;void inner() register int x=2; printf(%dn,x); 3、静态局部存储变量

44、、静态局部存储变量 局部静态存储变量与自动存储变量一样,是定义在某一函数内的变量,但与局部静态存储变量与自动存储变量一样,是定义在某一函数内的变量,但与自动存储变量不同的是局部静态存储变量的值不会因函数执行结束而消失。所以自动存储变量不同的是局部静态存储变量的值不会因函数执行结束而消失。所以如果再次回到函数内执行时,上次执行后,局部静态存储变量的值仍然在。如果再次回到函数内执行时,上次执行后,局部静态存储变量的值仍然在。局部静态存储变量的定义格式:局部静态存储变量的定义格式: static 类型说明符类型说明符 变量名变量名=初始化常量表达式初始化常量表达式,.;性质:性质:1)作用域的有限性

45、。)作用域的有限性。(同自动存储变量同自动存储变量)2)值的永久性。)值的永久性。3)可见性与存在性的不一致性。)可见性与存在性的不一致性。4)未初始化的值为)未初始化的值为0或或0。变量的存储类别变量的存储类别02自动存储变量局部静态存储变量#include int main() void increment(); increment(); increment(); increment(); return 0; void increment() int x=0; x=x+1; printf(%dn,x);result: 1 1 1#include int main() void increm

46、ent(); increment(); increment(); increment(); return 0; void increment() static int x=0; x=x+1; printf(%dn,x);result: 1 2 3 4、外部变量、外部变量(全局变量全局变量) 外部变量是指定义在文件中的所有函数之外的变量。在定义时,不必外部变量是指定义在文件中的所有函数之外的变量。在定义时,不必加关键字加关键字“extern”,但在声明时必须加但在声明时必须加“extern”关键字。关键字。 性质:性质: 1)作用域的全局性。作用域的全局性。 2)值的永久性。值的永久性。 3)可

47、见性与存在性的一致性。可见性与存在性的一致性。 4)未初始化的值为未初始化的值为0或或0。变量的存储类别变量的存储类别02外部变量的两种情况:外部变量的两种情况: 1) 限定只本文件内使用的外部变量。此时在定义时须加关键字限定只本文件内使用的外部变量。此时在定义时须加关键字static。通。通过声明可将过声明可将外部变量的作用域可以在本文件内延伸。称为外部变量的作用域可以在本文件内延伸。称为静态全局变量静态全局变量。2) 可在本程序的其他文件中使用的外部变量。此时在定义时不能加关键可在本程序的其他文件中使用的外部变量。此时在定义时不能加关键字字static。通过声明可将此。通过声明可将此外部变

48、量的作用域延伸到本程序的其他文件中。外部变量的作用域延伸到本程序的其他文件中。 这两种情况下,对外部变量的作用域进行延伸时都必须对外部变量进这两种情况下,对外部变量的作用域进行延伸时都必须对外部变量进行声明,声明方式为:行声明,声明方式为: extern 类型说明符类型说明符 变量名变量名;变量的存储类别变量的存储类别023)静态局部变量和静态全局变量的)静态局部变量和静态全局变量的区别区别定义的位置不同定义的位置不同静态局部变量在函数内定义静态局部变量在函数内定义静态全局变量在函数外定义静态全局变量在函数外定义作用域不同作用域不同静态全局变量为定义它的源文件内静态全局变量为定义它的源文件内静

49、态局部变量仅限于定义它的函数内静态局部变量仅限于定义它的函数内变量的存储类别变量的存储类别02外部变量的作用域在同一个文件中延伸#include void main() void gx(),gy(); extern int x,y; printf(1:x=%d y=%dn,x,y); y=246; gx(); gy();void gx() extern x,y; x=135; printf(2:x=%d y=%dn,x,y);int x,y;void gy() printf(3:x=%d y=%dn,x,y);变量的存储类别变量的存储类别02外部变量的作用域在不同文件中延伸file1.c#in

50、clude int a;void main() int power(); int b=3,c,d,m; scanf(%d,%d,&a,&m); c=a*b; printf(%d*%d=%dn,a,b,c); d=power(m); printf(%d*%d=%dn,a,m,d);file2.cextern int a;int power(int n) int i,y=1; for(i=1;i=n;i+) y=y*a; return y;编译预处理7.7 文件包含宏定义条件编译编译预处理编译预处理 概念:概念: 在进行编译的第一遍扫描在进行编译的第一遍扫描(词法扫描和语法分析词法扫描和语法分析)

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 大学资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com