1、第七章第七章第1页l l 本章关键点第2页l l 主要内容 7.1 7.1 函数概述函数概述 7.7.函数定义普通形式函数定义普通形式 7.7.函数参数和函数值函数参数和函数值 7.7.函数调用函数调用 7.7.函数嵌套调用函数嵌套调用 第3页l l 主要内容 7.6 7.6 函数递归调用函数递归调用 7.7 7.7 数组作为函数参数数组作为函数参数 7.8 7.8 变量作用域变量作用域-局部变量和全局变量局部变量和全局变量 7.9 7.9 变量存放方式和生存期变量存放方式和生存期 7.10 7.10 关于变量申明和定义关于变量申明和定义 7.11 7.11 内部函数和外部函数内部函数和外部函
2、数第4页 7.1 7.1 函数概述函数概述 一个程序可由一个主函数和若干个其它函数组成。一个较大程序可分为若干个程序模块,每一个模块用来实现一个特定功效。在高级语言中用子程序实现模块功效。子程序由函数来完成。函数间调用关系:由主函数调用其它函数,其它函数也能够相互调用。同一个函数能够被一个或多个函数调用任意屡次。第5页第6页例例7.17.1函数调用简单例子函数调用简单例子#include void main()void printstar();/*对对printstar函数申明函数申明*/void print_message();/*对对print_message函数申明函数申明*/print
3、star();*调用调用printstar函数函数*print_message();/*调用调用print_message函数函数*/printstar();*调用调用printstar函数函数*/第7页void printstar()*定义定义printstar函数函数*printf(*n);void print_message()*定义定义print_message函数函数*printf(How do you do!n);运行情况以下:运行情况以下:*How do you do!How do you do!*第8页 说明:1.一个程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文
4、件。对于较大程序,通常将程序内容分别放在若干个源文件中,再由若干源程序文件组成一个C程序。这么便于分别编写、分别编译,提高调试效率。一个源程序文件可认为多个C程序公用。第9页 说明:说明:2.一个源程序文件由一个或多个函数以及其它相关内容(如命令行、数据定义等)组成。一个源程序文件是一个编译单位,在程序编译时是以源程序文件为单位进行编译,而不是以函数为单位进行编译。第10页说明:说明:3.程序执行是从main函数开始,假如在main函数中调用其它函数,在调用后流程返回到main函数,在main函数中结束整个程序运行。第11页 说明:说明:4.全部函数都是平行,即在定义函数时是分别进行,是相互独
5、立。一个函数并不隶属于另一函数,即函数不能嵌套定义。函数间能够相互调用,但不能调用main函数。main函数是系统调用。第12页说明:说明:5.从用户使用角度看,函数有两种:标准函数,即库函数。这是由系统提供,用户无须自己定义这些函数,能够直接使用它们。不一样C系统提供库函数数量和功效会有一些不一样,但许多基本函数是共同。用户自己定义函数。用以处理用户专门需要。第13页说明:说明:6.从函数形式看,函数分两类:无参函数。无参函数普通用来执行指定一组操作。在调用无参函数时,主调函数不向被调用函数传递数据。有参函数。主调函数在调用被调用函数时,经过参数向被调用函数传递数据。第14页7.7.函数定义
6、普通形式函数定义普通形式 7.2.1.7.2.1.为何要定义函数为何要定义函数 C语言要求,在程序中用到全部函数,必须“先定义,后使用”。定义函数包含以下几个内容:指定函数名字,方便以后按名调用。指定函数类型,函数值类型。指定函数参数名字和类型,方便在调用函数时向它们传递数据。对无参函数不需要这项。指定函数应该执行什么操作,也就是函数是做什么,即函数功效。这是最主要。第15页7.7.函数定义普通形式函数定义普通形式 7.2.1.7.2.1.为何要定义函数为何要定义函数 对于C编译系统提供库函数,是由编译系统事先定义好,程序设计者无须自已定义,只需#include命令把相关头文件包含到本文件模块
7、中即可。比如,在程序中若用到数学函数(如sqrt,fabs,sin,cos等),就必须在本文件模块开头写上:#include 第16页7.7.函数定义普通形式函数定义普通形式7.2.2 7.2.2 怎样定义无参函数怎样定义无参函数定义无参函数普通形式为定义无参函数普通形式为:类型标识符类型标识符函数名函数名()()申明部分申明部分 语句部分语句部分 第17页7.7.函数定义普通形式函数定义普通形式7.2.3 7.2.3 怎样定义有参函数怎样定义有参函数定义有参函数普通形式为定义有参函数普通形式为:类型标识符类型标识符函数名函数名(形式参数表列)(形式参数表列)申明部分申明部分 语句部分语句部分
8、 比如:比如:(int,int);/*函数体中申明部分*?;return();第18页7.7.函数定义普通形式函数定义普通形式7.2.4 7.2.4 定义空函数定义空函数定义空函数普通形式为定义空函数普通形式为:类型标识符类型标识符函数名函数名()()比如:比如:void dummy()()主调函数调用空函数时,只表明这里要调用一个函数,但函数本身什么工作也不做等,以后扩充函数功效时补充上。第19页7.7.函数参数和函数值函数参数和函数值7.7.形式参数和实际参数形式参数和实际参数 形式参数:函数名后面括弧中变量名称为“形式参数”(简称“形参形参”);实际参数:主调函数中调用一个函数时,函数名
9、后面括弧中参数(能够是一个表示式)称为“实际参数”(简称“实参实参”);函数返回值:return后面括弧中值作为函数带回值(称函数返回值函数返回值)。第20页 主调函数和被调用函数之间有数据传递关系。在不一样函数之间传递数据,能够使用方法有:参数:经过形式参数和实际参数返回值:用return语句返回计算结果全局变量:外部变量第21页例例7.输输入入两两个个整整数数,要要求求用用一一个个函函数数求求出出其其中中大大者者,并在主函数中输出此值。并在主函数中输出此值。#include void()int max(int,int);/*对函数申明*/int,;scanf(,);(,);printf(,
10、);第22页int max(int,int)*定义有参函数max*int;?;return();运行情况以下:运行情况以下:,第23页经过函数调用,可使两个函数中数据发生联络。第24页关于形参加实参说明:关于形参加实参说明:1.1.在定义函数中指定形参,在未出现函数调用时,它们并不占内存中存放单元。只有在发生函数调用时,函数max中形参才被分配内存单元。在调用结束后,形参所占内存单元也被释放。2.2.实参能够是常量、变量或表示式,比如:比如:max(,);但要求它们有确定值。在调用时将实参值赋给形参。第25页3.3.在被定义函数中,必须指定形参类型。4.4.实参加形参类型应相同或赋值兼容。5.
11、5.实参向形参数据传递是单向“值传递”,只能由实参传给形参,而不能由形参传回来给实参。在调用函数时,给形参分配存放单元,并将实参对应值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。第26页7.7.函数参数和函数值函数参数和函数值7.3.2 7.3.2 函数返回值函数返回值函数返回值函数返回值是经过函数调用使主调函数得到确实定值。比如比如:例8.中,max(,)值是,max(,)值是5。赋值语句将这个函数值赋给变量。第27页说明:说明:1.函数返回值是经过函数中return语句取得。一个函数中能够有一个以上return语句,执行到哪一个return语句,哪一个语句起作用。re
12、turn语句后面括弧也能够不要比如比如:“return;”等价于等价于“return();();”return后面值能够是一个表示式。比如比如:(int,int)return(?:););第28页2.函数返回值应该属于某一个确定类型,在定义函数时指定函数返回值类型。比如比如:下面是下面是3个函数首行:个函数首行:int max(float,float)/*函数值为整型*/char letter(char c1,char c2)/*函数值为字符型*/double min(int,int)/*函数值为双精度型*/注意:注意:凡不加类型说明函数,自动按整型处理。第29页3.在定义函数时指定函数类型普
13、通应该和return语句中表示式类型一致。假如函数值类型和return语句中表示式值不一致,则以函数类型为准。对数值型数据,能够自动进行类型转换。即函数类型决定返回值类型。4.对于不带回值函数,应该用“void”定义函数为“无类型”(或称“空类型”)。此时在函数体中不得出现return语句。第30页例例 7.7.返回值类型与函数类型不一样返回值类型与函数类型不一样#include void main()int(float,float);float,;int;scanf(,);(,);printf(,);int max(float,float)float;/*z为实型变量*/?;return()
14、;运行情况以下:,Max is 第31页7.7.函数调用函数调用 7.4.1 7.4.1 函数调用普通形式函数调用普通形式函数调用普通形式为函数调用普通形式为:函数名函数名(实参表列)(实参表列)说明说明:1.1.假如是调用无参函数,则“实参表列”能够没有,但括弧不能省略。2.假如实参表列包含多个实参,则各参数间用逗号隔开。实参加形参个数应相等,类型应匹配。实参加形参按次序对应,向形参传递数据。第32页假如实参表列包含多个实参,对实参求值顺序并不是确定,有系统按自左至右次序求实参值,有系统则按自右至左次序。比如:(,+);若原值为,在 VC+6.0环境下运行结果不是“3,4”,而为“4,4”。
15、因为按自右而左次序,先求+i得4,再向左进行,此时i已是4了。假如想输出3和4,应写成:i=3;j=i+;printf(”%d,%d”,i,j);第33页7.7.函数调用函数调用7.4.2 7.4.2 函数调用方式函数调用方式函数语句函数语句把函数调用作为一个语句。这时不要求函数带回值,只要求函数完成一定操作。函数表示式函数表示式函数出现在一个表示式中,这种表示式称为函数表示函数表示式式。这时要求函数带回一个确定值以参加表示式运算。比如:*(,);(,);按函数在程序中出现位置来分,能够有按函数在程序中出现位置来分,能够有以下三种函数调用方式:以下三种函数调用方式:第34页函数参数函数参数函数
16、调用作为一个函数实参。比如比如:m=max(a,max(b,c);其中max(b,c)是一次函数调用,它值作为max另一次调用实参。m值是a、b、c三者中最大者。第35页7.7.函数调用函数调用 7.4.3 7.4.3 对被调用函数申明和函数原型对被调用函数申明和函数原型1.首先被调用函数必须是已经存在函数(是库函数或用户自己定义函数)。但光有这一条件还不够。第36页3.假如使用用户自己定义函数,而该函数位置在调用它函数(即主调函数)后面,应该在主调函数中对被调用函数作申明。2.假如使用库函数,还应该在本文件开头用#include 命令将调用相关库函数时所需用到信息“包含”到本文件中来。第37
17、页例例7.4 对被调用函数作申明对被调用函数作申明#include void main()float add(float x,float y);*对被调用函数add申明*float a,b,c;scanf(f,f,a,b);cadd(a,b);printf(sum is f n,c);float add(float,float)*函数首部*float;/*函数体*/z;return(z);运行情况以下:3.6,6.5Sum is 10.100000 第38页函数原型普通形式为函数原型普通形式为:1.1.函数类型函数类型 函数名函数名(参数类型参数类型1 1,参数类型,参数类型2)2);2.2.
18、函数类型函数类型 函数名函数名(参数类型参数类型1 1,参数名,参数名1 1,参数类型,参数类型2 2,参数名,参数名2)2);申明作用是把函数名、函数参数个数和参数类型等信息通知编译系统,方便在碰到函数调用时,编译系统能正确识别函数并检验调用是否正当。第39页注意:注意:函数“定义”和“申明”不是一回事。函数定义是指对函数功效确实立函数功效确实立,包含指定函数名,函数值类型、形参及其类型、函数体函数体等,它是一个完整、独立函数单位。函数申明作用则是把函数名字、函数类型以及形参类型、个数和次序通知编译系统,方便在调用该函数时系统按此进行对照检验。它不包含函数体函数体。第40页说明:说明:(1)
19、假如被调用函数定义出现在主调函数之前,能够无须加以申明。(2)假如已在文件开头(在全部函数之前),已对本文件中所调用函数进行了申明,则在各函数中无须对其所调用函数再作申明。第41页例例7.5(例例7.4改写)改写)#include float add(float,float)*函数首部*float;z;return(z);void main()/*无须再对add函数作申明*/float a,b,c;scanf(f,f,a,b);cadd(a,b);printf(sum is f n,c);第42页 7.7.函数嵌套调用函数嵌套调用嵌套定义就是在定义一个函数时,其函数体内又包含另一个函数完整定义
20、。第43页在主函数中调用一个max_4函数来求4个整数中最大数。然后在max_4函数中再调用一个max_2函数来求2个整数中最大数。最终在主函数中输出结果。方法:方法:例例7.6 输入4个整数,找出其中最大数。用函数嵌套调用来处理。第44页#include void main()int max_4(int a,int b,int c,int d);/*max_4函数申明*/int a,b,c,d,max;printf(Please enter 4 interger numbers:);scanf(%d%d%d%d,&a,&b,&c,&d);max=max_4(a,b,c,d);/*调用max_
21、4函数*/printf(max=%d n,max);int max_4(int a,int b,int c,int d)/*max_4函数定义*/int max_2(int,int);/*max_2函数申明*/int m;第45页 m=max_2(a,b);/*调用max_2函数*/m=max_2(m,c);/*调用max_2函数*/m=max_2(m,d);/*调用max_2函数*/return(m);/*函数返回值是4个数中最大者*/int max_2(a,b)/*max_4函数定义*/int max_2(a,b)if(ab)return a;else return b;/*函数返回值是a
22、和b中大者*/运行情况以下:运行情况以下:Please enter 4 interger numbers:11 45 54 0Please enter 4 interger numbers:11 45 54 0max=45max=45第46页 7.6 7.6 函数递归调用函数递归调用 在调用一个函数过程中又出现直接或间接地调用该函数本身,称为函数递归调用。语言特点之一就在于允许函数递归调用。比如:比如:int f(int),;();/*在执行f函数过程中又要 调用f函数*/return(*);第47页例例 7.7:7.7:有个人坐在一起,问第个人多少岁?他说比第个人大岁。问第个人岁数,他说比第
23、个人大岁。问第个人,又说比第个人大岁。问第个人,说比第个人大岁。最终问第个人,他说是岁。请问第个人多大。age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10能够用数学公式表述以下:age(n)=10()age(n-1)+2()第48页能够用一个函数来描述上述递归过程:能够用一个函数来描述上述递归过程:int age(int)*求年纪递归函数*int;*用作存放函数返回值变量*if();else ();return();运行结果以下:运行结果以下:用一个主函数调用age函数,求得第5人年纪。#include v
24、oid main()printf(,age();第49页例例7.8 7.8 用递归方法求!用递归方法求!求!也能够用递归方法,即!等于!,而!。可用下面递归公式表示:!(,)=()!()第50页程序以下:程序以下:#include void main()long fac(int n);/*对fac函数申明*/int n;long y;printf(input an integer number:);scanf(%d,&n);y=fac(n);printf(%d!=%ldn,n,y);第51页long fac(int n)/*定义fac函数*/long f;if(n0)printf(n0,dat
25、a error!);else if(n=0,n=1)f=1;else f=fac(n-1)*n;return(f);运行情况以下:运行情况以下:an integer nunber:10!=3628800第52页例例7.9 Hanoi(汉诺塔)问题(汉诺塔)问题:第53页由上面分析可知:将个盘子从座移到座能够分解为以下3个步骤:1.将上个盘借助座先移到座上。2.把座上剩下一个盘移到座上。3.将个盘从座借助于座移到座上。第54页程序以下:程序以下:#include void main()void hanoi(int n,char one,char two,char three);/*对hanoi函
26、数申明*/int m;printf(input the number of diskes:);scanf(“%d”,&m);printf(The step to moveing%d diskes:n,m);hanoi(m,A,B,C);第55页void hanoi(int n,char one,char two,char three)/*定义hanoi函数,将个盘从one座借助two座,移到three座*/void move(char x,char y);/*对move函数申明*/if(n=1)move(one,three);else hanoi(n-1,one,three,two);move
27、(one,three);hanoi(n-1,two,one,three);void move(char x,char y)/*定义move函数*/printf(“%c-%cn,x,y);第56页运行情况以下:运行情况以下:input the number of diskes:3 The steps to noving 3 diskes:第57页7.7 7.7 数组作为函数参数数组作为函数参数7.7.1 7.7.1 数组元素作函数实参数组元素作函数实参 因为实参能够是表示式,而数组元素能够是表示式组成部分,所以数组元素能够作为函数实参,与用变量作实参一样,是单向传递,即“值传送”方式。第58页例
28、例 7.10 7.10 有两个数组和,各有个元素,将它们对应地逐一相比(即与比,与比)。假如数组中元素大于数组中对应元素数目多于b数组中元素大于a数组中对应 元 素 数 目(比 如,a i b i 6次,biai3次,其中i每次为不一样值),则认为a数组大于b数组,并分别统计出两个数组对应元素大于、等于、小于次数。第59页#include void main()int large(int x,int y);/*函数申明*/int 10,10,,;printf(enter array a);for(;)scanf(,);printf();printf(enter array);for(;)sca
29、nf(,);printf();for(;)if(large(i,i)=);else if(large(i,i)=)=+;else;第60页printf(aibi%d timesnai=bi%d timesnaik)printf(array a is larger than array bn);else if(nk)printf(array a is smaller than array bn);else printf(array is equal to array bn);large(int,int)int;if();else if()flag;else flag;return(flag);第
30、61页运行情况以下:运行情况以下:enter array a:5 3 8 9 1 3 5 6 0 4 array a is smaller thann array b第62页7.7 7.7 数组作为函数参数数组作为函数参数7.7.2 7.7.2 数组名作函数参数数组名作函数参数 能够用数组名作函数参数,此时形参应该用数组名或用指针变量。例例7.11 有一个一维数组score,内放10个学生成绩,求平均成绩。第63页#include void main()float average(float array10);/*函数申明*/float score10,aver;int;printf(inpu
31、t scores:);for(;scanf(,score);printf();averaverage(score);printf(average score is.n,aver);第64页float average(float array10)int;float aver,;for (;);return(aver);运行情况以下:运行情况以下:input scores:.5 .5 average score is 83.40 第65页例例7.编写一个函数,用来分别求数组编写一个函数,用来分别求数组score_1和和数组数组score_2各元素平均值。各元素平均值。#include void m
32、ain()float average(float ,int)float score_15,.,;float score_210=67.5,89.5,99,6.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);第66页float average(float ,int)int;float aver,;for(;sumsumarray;aversum;retu
33、rn();运行结果以下:运行结果以下:the average of class A is 80.40The average of class is 78.20第67页例例 7.13 用选择法对数组中10个整数按由小到大排序。所谓选择法就是先将10个数中最小数与a0对换;再将a1到a9中最小数与a1对换每比较一轮,找出一个未经排序数中最小一个。共比较9轮。第68页未排序时情况:a0 a1 a2 a3 a4 3 6 1 9 4 将5个数中最小数1与a0对换:1 6 3 9 4 将余下4个数中最小数3与a1对换 1 3 6 9 4 将余下3个数中最小数4与a2对换 1 3 4 9 6 将余下2个数中
34、最小数6与a3对换,至此完成排序 1 3 4 6 9 第69页程序实例程序实例#include void main()void sort(int,int);int,;printf(enter the array);for(;scanf(,);sort(,);printf(the sorted array);for(;printf(,);printf();第70页void sort(int array,int)int,;for(;);for(;)if(array array=;=arrayk;arrayk=arrayi;arrayi=t 运行结果以下:运行结果以下:enter array:5 7
35、 3 21 43 67 321 33 51 0 The sorted array:43 3 0 5 7 21 33 51 67 321第71页7.7 7.7 数组作为函数参数数组作为函数参数7.7.3 7.7.3 用多维数组名作函数参数用多维数组名作函数参数 多维数组元素能够作函数参数,这点与用一维数组元 素作函数参数情况类似。也能够用多维数组名作为函数实参和形参,在被调用函数中对形参数组定义时能够指定每一维大小,也能够省略第一维大小说明。例例7.14有一个二维数组,设计一个函数,用来求二维数组中全部元素中最大值。第72页程序以下:程序以下:#include void main()max_va
36、lue(int 4);int 34=1,3,5,7,2,4,6,8,15,17,34,12;printf(max value is,max_value(a));算法:先使变量max初值为二维数组中第一个元素值,然后将二维数组中各个元素值与max相比,每次比较后都把“大者”存放在max中,全部元素比较完后,max 值就是全部元素最大值。第73页max_value(int array 4)int,max;max=;for(=;)for(;if(array)max=array;return(max);运行结果以下:运行结果以下:Max value is 34第74页7.8 7.8 变量作用域变量作用
37、域-局部变量和全局变量局部变量和全局变量7.8.1 7.8.1 局部变量局部变量 在一个函数内部定义变量是内部变量,它只在本函数范围内有效,也就是说只有在本函数内才能使用它们,在此函数以外是不能使用这些变量。这称为“局部变量”。第75页float f1(int a)/*函数f1*/int b,c;a、b、c有效 char f2(int x,int y)/*函数f2*/int i,j;x、y、i、j有效 void main()/*主函数*/int m,n;m、n有效 第76页(1)主函数中定义变量只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其它函数中定义变量
38、。(2)不一样函数中能够使用相同名字变量,它们代表不一样对象,互不干扰。(3)形式参数也是局部变量。(4)在一个函数内部,能够在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为“分程序”或“程序块”。第77页void main()int a,b;int c;c=a+b;c在此范围内有效 a,b在此范围内有效 第78页7.8 7.8 变量作用域变量作用域-局部变量和全局变量局部变量和全局变量7.8.2 7.8.2 全局变量全局变量在函数内定义变量是局部变量,而在函数之外定义变量称为外部变量,外部变量是全局变量(也称全程变量)。全局变量可认为本文件中其他函数所共用。它有效范围为
39、从定义变量位置开始到根源文件结束。第79页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;全局变量p,q作用范围 全局变量c1,c2作用范围void main()/*主函数*/int m,n;第80页例 7.15 有一个一维数组,内放个学生成绩,写一个函数,求出平均分、最高分和最低分。#include float Max,Min;*全局变量*void main()float average(float array,int n
40、);float ave,score10;int;for(;)scanf(,);ave=average(,);printf(“max=%6.2fnmin=%6.2fn average=%6.2fn“,Max,Min,ave);第81页float average(float array,int n)*定义函数,形参为数组*/int;float aver,sum=array;Max=Min=array;for(=;)if(arrayMax)Maxarray;else if(arrayMin)Min array;sum=sum+array;aver;return();运行情况以下:运行情况以下:第82
41、页第83页提议不在必要时不要使用全局变量,原因以下:全局变量在程序全部执行过程中都占用存放单元,而不是仅在需要时才开辟单元。使用全局变量过多,会降低程序清楚性。在各个函数执行时都可能改变外部变量值,程序轻易犯错。所以,要限制使用全局变量。第84页它降低函数通用性,因为函数在执行时要依赖于其所在外部变量。假如将一个函数移到另一个文件中,还要将相关外部变量及其值一起移过去。但若该外部变量与其它文件变量同名时,就会出现问题,降低了程序可靠性和通用性。普通要求把程序中函数做成一个封闭体,除了能够经过“实参形参”渠道与外界发生联络外,没有其它渠道。第85页例例 7.7.6 6 外部变量与局部变量同名外部
42、变量与局部变量同名#include int a=3,b=5;/*a,b为外部变量*/a,b作用范围void main()int a=8;/*a为局部变量*/局部变量a作用范围 printf(%d,max(a,b);全局变量b作用范围 max(int a,int b)/*a,b为局部变量*/int c;c=ab?ab;形参a、b作用范围 return(c);运行结果为运行结果为 8 第86页 7.7.变量存放方式和生存期变量存放方式和生存期 从变量作用域作用域(即从空间)角度来分,能够分为全局变量和局部变量。从变量值生存期生存期(即存在时间)角度来分,又能够分为静态存放方式和动态存放方式。第87
43、页 7.7.变量存放方式和生存期变量存放方式和生存期 所谓静态存放方式是指在程序运行期间由系统分配固定存放空间方式。动态存放方式则是在程序运行期间依据需要进行动态分配存放空间方式。这个存放空间能够分为三部分:1.1.程序区程序区 2.2.静态存放区静态存放区 3.3.动态存放区动态存放区 在语言中每一个变量和函数有两个属性:数据类型数据类型和数据存放类别数据存放类别。第88页7.7.变量存放方式和生存期变量存放方式和生存期7.9.1 7.9.1 局部变量存放类别局部变量存放类别 1.auto变量变量:函数中局部变量,如不专门申明static存放类别,都是动态地分配存放空间,数据存放在动态存放区
44、中。函数中形参和在函数中定义变量(包含在复合语句中定义变量),都属这类,在调用该函数时系统会给它们分配存放空间,在函数调用结束时就自动释放这些存放空间。所以这类局部变量称为自动变量。自动变量用关键字作存放类别申明。比如:比如:int(int)*定义f函数,为形参*auto int,;/*定义、为自动变量*第89页2.静态局部变量:静态局部变量:当函数中局部变量值在函数调用结束后不消失而保留原值时,该变量称为静态局部变量。用关键字static进行申明。7.7.变量存放方式和生存期变量存放方式和生存期7.9.1 7.9.1 局部变量存放类别局部变量存放类别第90页例例77 考查静态局部变量值#in
45、clude void main()int(int);,;(;(,();int(int)int;();第91页对静态局部变量说明:对静态局部变量说明:1.静态局部变量属于静态存放类别,在静态存放区内分配存放单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存放类别,占动态存放区空间而不占静态存放区空间,函数调用结束后即释放。2.对静态局部变量是在编译时赋初值,即只赋初值一次,在程序运行时它已经有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时值。第92页3.如在定义局部变量时不赋初值话,则对静态局部变量来说,编译时自动赋初值(对数值型变量)或空字符(对字符变
46、量)。而对自动变量来说,假如不赋初值则它值是一个不确定值。4.即使静态局部变量在函数调用结束后依然存在,但其它函数不能引用它。第93页例例78 输出到阶乘值#include void main()int fac(int);int;for(;)printf(%!=,fac();Int fac(int)static int;*;return();第94页 3.存放器变量存放器变量(register):):变量值是存放在内存中。当程序中用到哪一个变量值时,由控制器发出指令将内存中该变量值送到运算器中。经过运算器进行运算,假如需要存数,再从运算器将数据送到内存存放。7.7.变量存放方式和生存期变量存放
47、方式和生存期7.9.1 7.9.1 局部变量存放类别局部变量存放类别第95页 假如有一些变量使用频繁,则为存取变量值要花费不少时间。为提升执行效率,语言允许将局部变量值放在CPU中存放器中,需要用时直接从存放器取出参加运算,无须再到内存中去存取。因为对存放器存取速度远高于对内存存取速度,所以这么做能够提升执行效率。这种变量叫做存放器变量存放器变量,用关键字register作申明。7.7.变量存放方式和生存期变量存放方式和生存期7.9.1 7.9.1 局部变量存放类别局部变量存放类别 说明:三种局部变量存放位置是不一样:自动变量存放在动态存放区;静态局部变量存放在静态存放区;存放器存放在CPU中
48、存放器中。第96页7.变量存放方式和生存期变量存放方式和生存期7.9.2 全局变量存放类别全局变量存放类别 全局变量都是存放在静态存放区中。所以它们生存期是固定,存在于程序整个运行过程。一般来说,外部变量是在函数外部定义全局变量,它作用域是从变量定义处开始,到本程序文件末尾。在此作用域内,全局变量可认为程序中各个函数所引用。但有时程序设计人员希望能扩展外部变量作用域。方法有以下几个:第97页1.在一个文件内扩展外部变量作用域在一个文件内扩展外部变量作用域例例7.19调用函数,求调用函数,求3个整数中大者。个整数中大者。#include void main()int max();/*函数申明*/
49、extern int A,B,C;/*外部变量申明*/printf(Please enter three integer numbers:);scanf(%d%d%d,&A,&B,&C);/*输入外部变量值*/printf(max is%dn,max();第98页1.在一个文件内扩展外部变量作用域在一个文件内扩展外部变量作用域int A,B,C;/*定义外部变量*/int max()int m;m=AB?A:B;if(Cm)m=C;return(m);运行结果为:运行结果为:Please enter three integer numbers:34 21 78 max is 78第99页2.将
50、外部变量作用域扩展到其它文件将外部变量作用域扩展到其它文件#include int A;/*定义外部变量*/void main()int(int);/*函数申明*/int,;printf(enter the number a and its power m:n);scanf(,A,);A*;printf(*,A,);();printf(*n,A,);例例7.207.20 用extern将外部变量作用域扩展到其它文件。本程序作用是给定值,输入和,求和am值。文件file.中内容为:第100页文件file中内容为:extern A;/*申明A为一个已定义外部变量*/int(int);int,;fo