1、第六章第六章第1页l l 本讲关键点第2页l l 主要内容 6.3 6.3函数参数函数参数 6.4 6.4函数指针函数指针 6.5 6.5 指针型函数指针型函数 6.7 6.7变量作用域与存放类型变量作用域与存放类型 第3页 6.26.2函数参数函数参数1 1、数组元素作函数实参数组元素作函数实参因为实参能够是表示式,而数组元素能够是表示式组成部分,所以数组元素能够作为函数实参,与用变量作实参一样,是单向传递,即“值传送”方式。一、一、数组作函数实参数组作函数实参第4页例例 6.10 6.10 有两个数组和,各有个元素,将它们对应地逐一相比(即与比,与比)。假如数组中元素大于数组中对应元素数目
2、多于b数组中元素大于a数组中对应 元 素 数 目(比 如,a i b i 6次,biai3次,其中i每次为不一样值),则认为a数组大于b数组,并分别统计出两个数组对应元素大于、等于、小于次数。第5页#includevoidmain()intlarge(intx,inty);/*函数申明*/int10,10,,;printf(enterarraya);for(;)scanf(,);printf();printf(enterarray);for(;)scanf(,);printf();for(;)if(large(i,i)=);elseif(large(i,i)=)=+;else;第6页print
3、f(aibi%dtimesnai=bi%dtimesnaik)printf(arrayaislargerthanarraybn);elseif(nk)printf(arrayaissmallerthanarraybn);elseprintf(arrayisequaltoarraybn);large(int,int)int;if();elseif()flag;elseflag;return(flag);第7页运行情况以下:运行情况以下:enter array a:5 3 8 9 1 3 5 6 0 4 array a is smaller thann array b第8页2 2、数组名作函数参数
4、数组名作函数参数 用数组名作函数参数时,此时形参应该用数组名或用指针变量。例例6.11 有一个一维数组score,内放10个学生成绩,求平均成绩。第9页#includevoidmain()floataverage(floatarray10);/*函数申明*/floatscore10,aver;int;printf(inputscores:);for(;scanf(,score);printf();averaverage(score);printf(averagescoreis.n,aver);第10页floataverage(floatarray10)int;floataver,;for(;)
5、;return(aver);运行情况以下:运行情况以下:input scores:.5 .5 average score is 83.40第11页例例 6.6.形参数组不定义长度形参数组不定义长度#includevoidmain()floataverage(float,int)floatscore_15,.,;floatscore_210=67.5,89.5,99,6.5,77,89.5,76.5,54,60,99.5;printf(“theaverageofclassAis%6.2fn”,average(score_1,5);printf(“theaverageofclassBis%6.2f
6、n”,average(score_2,10);第12页floataverage(float,int)int;floataver,;for(;sumsumarray;aversum;return();运行结果以下:运行结果以下:the average of class A is 80.40The average of class is 78.20第13页例例 6.13 用选择法对数组中10个整数按由小到大排序。所谓选择法就是先将10个数中最小数与a0对换;再将a1到a9中最小数与a1对换每比较一轮,找出一个未经排序数中最小一个。共比较9轮。第14页未排序时情况:a0a1a2a3a436194将5
7、个数中最小数1与a0对换:16394将余下4个数中最小数3与a1对换13694将余下3个数中最小数4与a2对换13496将余下2个数中最小数6与a3对换13469第15页程序:程序:#includevoidmain()voidsort(int,int);int,;printf(enterthearray);for(;scanf(,);sort(,);printf(thesortedarray);for(;printf(,);printf();第16页voidsort(intarray,int)/*排序函数*/int,;for(;);for(;)if(arrayarray=;=arrayk;ar
8、rayk=arrayi;arrayi=t第17页(年9月全国计算机等级考试二级笔试原题)第18页年年3月全国计算机等级考试二级笔试试卷月全国计算机等级考试二级笔试试卷C语言程序设计试题语言程序设计试题C第19页例例614 将数组中个整数按相反次序存放。将数组中个整数按相反次序存放。第20页#include voidmain()voidinv(int,int);int,;printf(Theoriginalarray:);for(;)printf(,);printf();inv(,);printf(Thearrayhasbeeninverted:);for(;)printf(,);printf(
9、);第21页voidinv(int,int)/*形参x是数组名*/inttemp,();for(;);temp;temp;return;运行情况以下:运行情况以下:Theoriginalarray:,Thearrayhasbeeninverted:,第22页第23页#include voidmain()voidinv(int*,int);int,;printf(Theoriginalarray:);for(;)printf(,);printf();inv(,);printf(Thearrayhasbeeninverted:);for(;)printf(,);printf();对刚才程序能够作一
10、些改动。将函对刚才程序能够作一些改动。将函数数inv中形参改成指针变量。中形参改成指针变量。第24页void inv(int*,int)/*形参x为指针变量*/int,temp,*,*,();for(;,)emp*;*;*temp;return;第25页假如有一个实参数组,想在函数中改变此数假如有一个实参数组,想在函数中改变此数组中元素值,实参加形参对应关系有以下组中元素值,实参加形参对应关系有以下种情况:种情况:(1)形参和实参都用数组名,如:形参和实参都用数组名,如:voidmain()void(int,int)int;(,);第26页第27页(2)实参用数组名,形参用指针变量。如:实参用
11、数组名,形参用指针变量。如:void()void(int*,int)int;(,);(3)实参形参都用指针变量。比如:实参形参都用指针变量。比如:voidmain()void(int*,int)int,*p=a;(p,);第28页第29页(4)实参为指针变量,形参为数组名。如:实参为指针变量,形参为数组名。如:voidmain()void(intx,int),*p=a;(p,);第30页#include voidmain()voidinv(int*,int);int,*;printf(Theoriginalarray:n);for(;,)scanf(,);printf();inv(,);/*实
12、参为指针变量实参为指针变量*/printf(Thearrayhasbeeninverted:);for(;)printf(,*);printf();第31页voidinv(int*,int)int,temp,*,*;();for(;,)emp*;*;*temp;return;第32页(年9月全国计算机等级考试二级笔试原题)第33页3 3、多维数组名作函数参数、多维数组名作函数参数程序:程序:#includevoidmain()max_value(int4);int34=1,3,5,7,2,4,6,8,15,17,34,12;printf(maxvalueis,max_value(a));用多维
13、数组名作为函数实参和形参。在被调函数中对形参数组定义时能够指定每一维大小。第34页max_value(intarray4)int,max;max=;for(=;)for(;if(array)max=array;return(max);运行结果以下:运行结果以下:Max value is 34第35页(年9月全国计算机等级考试二级笔试原题)第36页(年9月全国计算机等级考试二级笔试原题)第37页(33)有以下程序#include#includevoidfun(char*s,intn)char*t;inti,j;for(i=0;in-1;i+)for(j=i+1;jstrlen(sj)t=si;s
14、i=sj;sj=t;main()char*ss=“bcc”,”bbcc”,”xy”,”aaaacc”,”aabcc”;fun(ss,5);printf(“%s,%sn”,ss0,ss4);程序运行结果是A)xy,aaaaccB)aaaacc,xyC)bcc,aabccD)aabcc,bcc(年4月全国计算机等级考试二级笔试原题)第38页三、字符串作函数参数三、字符串作函数参数将一个字符串从一个函数传递到另一个函数,将一个字符串从一个函数传递到另一个函数,能够采取地址传递方法,即将字符数组名作参数能够采取地址传递方法,即将字符数组名作参数或用指向字符串指针变量作参数。在被调用函数或用指向字符串指
15、针变量作参数。在被调用函数中能够改变字符串内容,在主调函数中能够得到中能够改变字符串内容,在主调函数中能够得到改变了字符串。改变了字符串。第39页例例6.15 用函数调用实现字符串复制用函数调用实现字符串复制#includevoidmain()voidcopy_string(charfrom,charto);chara=amateacher;char=youareastudent;printf(“stringa=string,);printf(“copystringatostringb:n”);copy_string(,);printf(nstringa=%snstringb=%sn,a,b)
16、;1、用字符数组作参数用字符数组作参数第40页voidcopy_string(charfrom,charto)int;while(from!)tofrom;to;程序运行结果以下程序运行结果以下:stringaIamateacherstringbyouareastudentcopystringatostringb:stringaIamateacherstringIamateacher第41页(2)形参用字符指针变量形参用字符指针变量#includevoidmain()voidcopy_string(char*from,char*);char*amateacher.;char*youareast
17、udent;printf(stringa=string,);printf(copystringatostringb:n);_(,);printf(nstringa=%snstringb=%sn,a,b);第42页voidcopy_string(char*,char*)for(;*from!;from,to)*tofrom;*to;(3)(3)对对copy string 函数还可作简化函数还可作简化1、将、将copy_string函数改写为函数改写为voidcopy_string(char*from,char*)while(*from)!)to;from;第43页 copy_string函数函数
18、体还可改为函数函数体还可改为while(*to*from)!);copy_string函数函数体还可写成函数函数体还可写成while(*from!)*to*from;*to;第44页上面上面while语句还能够深入简化为下面语句还能够深入简化为下面while语句:语句:while(*to*from);它与下面语句等价:while(*to*from)!);将*from赋给*to,假如赋值后*to值等于则循环终止(已赋给*to)函数体中函数体中while语句也能够改用语句也能够改用for语句:语句:for(;(*to*from)!;);或for(;*to*from;);第45页也可用指针变量,函数
19、也可用指针变量,函数copy_string可写为可写为voidcopy_string(charfrom,char)char*,*;from;while(*p2*p1)!);第46页例、有以下函数年9月全国计算机等级考试二级笔试原题intaaa(char*s)char*t=s;while(*t+);t-;return(t-s);以下关于aaa函数功效叙述正确是A、求字符串s长度B、比较两个串大小C、将串s复制到串tD、求字符串s所占字节数第47页年年3月全国计算机等级考试二级笔试试卷月全国计算机等级考试二级笔试试卷C语言程序设计试题语言程序设计试题fabcde第48页6.3 6.3 函数指针函数
20、指针1 1、用函数指针变量调用函数用函数指针变量调用函数l一个函数包含一组指令序列,存放在某一段内存中,这段内存空间起始地址称为函数入口地址l我们把函数入口地址为函数指针。函数名代表函数入口地址l能够定义一个指针变量,其值等于该函数入口地址,指向这个函数,这么经过这个指针变量也能调用这个函数。这种指针变量称为指向函数指针变量。第49页定义指向函数指针变量普通形式为:类型标识符(类型标识符(*指针变量名指针变量名)();例:例:int (*p)();/*指针变量指针变量p能够指向一个整型函数能够指向一个整型函数*/float (*q)();/*指针变量指针变量q能够指向一个浮点型函数能够指向一个
21、浮点型函数*/第50页l 我我们们能能够够把把定定义义指指向向函函数数指指针针变变量量,亦亦象象其其它它指指针针变变量量一一样样要要赋赋以以地地址址值值才才能能引引用用。当当将将某某个个函函数数入入口口地地址址赋赋给给指指向向函函数数指指针针变变量量,就就可可用用该该指指针针变变量量来调用所指向函数来调用所指向函数 l 给给函函数数指指针针赋赋初初值值:将将函函数数名名(函函数数入入口口地地址址值值)赋给指针变量赋给指针变量 比如、比如、int m,(*p)();int max(int a,int b);则能够则能够 p=max;/*p指向函数指向函数max()*/指针调用函数指针调用函数 普
22、通形式为:普通形式为:(*指针变量指针变量)(实参表实参表);如上例:如上例:m=(*p)(12,22);/*比较比较 m=max(12,22);*/第51页#includevoidmain()intmax(int,int);int,;scanf(,);(,);printf(,);intmax(int,int)int;if();else;return();第52页将main 函数改写为#includevoidmain()int(int,int);int(*)();int,;scanf(,);(*)(,);printf(,);第53页2 2、作用:、作用:用指向函数指针作函数参数用指向函数指针作
23、函数参数函数指针变量惯用用途之一是把指针作为参数传递到其它函数。指向函数指针也能够作为参数,以实现函数地址传递,这么就能够在被调用函数中使用实参函数。第54页实参函数名f1void(int(*x1)(int),int(*x2)(int,int))int,;(*)();*调用函数*(*)(,);*调用函数*第55页例例6.16 6.16 设一个函数设一个函数processprocess,在调用它时候,每次实现,在调用它时候,每次实现不一样功效。输入和两个数,第一次调用不一样功效。输入和两个数,第一次调用processprocess时找出和中大者,第二次找出其中小者,第三次求时找出和中大者,第二次
24、找出其中小者,第三次求与之和。与之和。#includevoidmain()intmax(int,int);/*函数申明*/intmin(int,int);/*函数申明*/intadd(int,int);/*函数申明*/voidprocess(int,int,int(*fun)();/*函数申明*/int,;printf(enteraandb:);scanf(,);第56页printf(max);process(,);printf(min);process(,);printf(sum);process(,);第57页intmax(int,int)/*函数定义*/int;if();else;ret
25、urn();intmin(int,int)/*函数定义*/int;if();else;return();第58页int(int,int)/*函数定义*/int;return();voidprocess(int,int,int(*fun)(int,int)intresult;result(*fun)(,);printf(,result);第59页B(年9月全国计算机等级考试二级笔试原题)第60页(1)定义一个指向函数指针变量,形如:定义一个指向函数指针变量,形如:float(*p)();(2)为函数指针赋值,格式以下:为函数指针赋值,格式以下:p=函数名;函数名;注意:赋值时只需给出函数名,不要
26、带参数。注意:赋值时只需给出函数名,不要带参数。(3)经过函数指针调用函数,调用格式以下:经过函数指针调用函数,调用格式以下:s=(*p)(实参实参);小结:指向函数指针使用步骤小结:指向函数指针使用步骤第61页6.4 6.4 返回指针值函数返回指针值函数一个函数能够带回一个整型值、字符值、实型值等,也能够带回指针型数据,即地址。其概念与以前类似,只是带回值类型是指针类型而已。这种带回指针值函数,普通定义形式为类型名类型名*函数名(参数表列)函数名(参数表列);比如:int*(int,int);第62页例例6 616 16 有若干个学生成绩(每个学生有门课程),有若干个学生成绩(每个学生有门课
27、程),要求在用户输入学生序号以后,能输出该学生全部成绩要求在用户输入学生序号以后,能输出该学生全部成绩。用指针函数来实现。用指针函数来实现。#includevoidmain()float*score4=60,70,80,90,56,89,67,88,34,78,90,66;float*search(float(*pointer)4,intn);float*;int,;printf(enterthenumberofstudent:);scanf(,);printf(ThescoresofNoare:,);第63页search(,);for(;printf(,*();float*search(fl
28、oat(*)4,int)float*;*();return();运行情况以下:运行情况以下:enterthenumberofstudent:ThescoresofNo.are:56.0089.0067.0088.00第64页例例6.17 对上例中学生,找出其中有不及格课程学对上例中学生,找出其中有不及格课程学生及其学生号。生及其学生号。#includevoidmain()floatscore4=60,70,80,90,56,89,67,88,34,78,90,66;floatsearch(float(*pointer)4);float*;i,;第65页for(;)search(score);(
29、*(score)printf(scores:,);for(;)printf(5.2,*();printf();第66页 6.76.7变量作用域与存放类型变量作用域与存放类型1 1、局部变量也称内部变量局部变量也称内部变量局部变量:在一个函数内部或在复合语句中定义变量称内部变量。它只在本函数范围内或复合语句内有效,即:只有在本函数内或复合语句内才能使用这些变量,故称为“局部变量”。一、一、局部变量与全局变量局部变量与全局变量第67页例:floatf1(inta)/*函数f1*/intb,c;/*a、b、c有效*/charf2(intx,inty)/*函数f2*/inti,j;/*x、y、i、j有
30、效*/voidmain()/*主函数*/intm,n;/*m、n有效*/第68页(1)主函数中定义变量只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其它函数中定义变量。(2)不一样函数中能够使用相同名字变量,它们代表不一样对象,互不干扰。(3)形式参数也是局部变量。(4)在一个函数内部,能够在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为“分程序”或“程序块”。第69页voidmain()inta,b;intc;c=a+b;c在此范围内有效a,b在此范围内有效第70页2 2、全局变量也称外部变量全局变量也称外部变量全局变量:函数之外定义
31、变量称为全局变量。全局变量能够为本文件中其它函数所共用。它有效范围为从定义变量位置开始到根源文件结束。所以又称全程变量。第71页intp=1,q=5;/*外部变量*/floatf1(inta)/*定义函数f1*/intb,c;charc1,c2;/*外部变量*/charf2(intx,inty)/*定义函数f2*/inti,j;全局变量p,q作用范围全局变量c1,c2作用范围voidmain()/*主函数*/intm,n;第72页例6.18 有一个一维数组,内放个学生成绩,写一个函数,求出平均分、最高分和最低分。#includefloatMax,Min;*全局变量*voidmain()floa
32、taverage(floatarray,intn);floatave,score10;int;for(;)scanf(,);ave=average(,);printf(“max=%6.2fnmin=%6.2fnaverage=%6.2fn“,Max,Min,ave);第73页floataverage(floatarray,intn)*定义函数,形参为数组*/int;floataver,sum=array;Max=Min=array;for(=;)if(arrayMax)Maxarray;elseif(arrayMin)Minarray;sum=sum+array;aver;return();运
33、行情况以下:运行情况以下:第74页第75页提议:无须要时不要使用全局变量,原因以下:全局变量在程序全部执行过程中都占用存放单元,而不是仅在需要时才开辟单元。使用全局变量过多,会降低程序清楚性。在各个函数执行时都可能改变外部变量值,程序轻易犯错。所以,要限制使用全局变量。第76页降低函数通用性。因为函数在执行时要依赖于其所在外部变量。假如将一个函数移到另一个文件中,还要将相关外部变量及其值一起移过去。但若该外部变量与其它文件变量同名时,就会出现问题,降低了程序可靠性和通用性。普通要求把程序中函数做成一个封闭体,除了能够经过“实参形参”渠道与外界发生联络外,没有其它渠道。第77页例例 6.6.8
34、8 外部变量与局部变量同名外部变量与局部变量同名#includeinta=3,b=5;/*a,b为外部变量*/a,b作用范围voidmain()inta=8;/*a为局部变量*/局部变量a作用范围printf(%d,max(a,b);全局变量b作用范围max(inta,intb)/*a,b为局部变量*/intc;c=ab?ab;形参a、b作用范围return(c);运行结果为运行结果为 8第78页(年9月全国计算机等级考试二级笔试原题)3025第79页intp=1,q=5;floatf1(inta)intb,c;.intf3().charc1,c2;charf2(intx,inty)inti,
35、j;main()intm,n;.c1,c2作用范围p,q作用范围externcharc1,c2;c1,c2作用范围扩展后externcharc1,c2;c1,c2作用范围扩展后第80页二、二、二、二、变量存放类别变量存放类别1 1、动态存放方式与静态存放方式动态存放方式与静态存放方式从变量作用域(即从空间)角度来分,能够分为全局变量和局部变量。从变量值存在时间角度来分,又能够分为静态存放方式和动态存放方式。静态存放方式:指在程序运行期间由系统分配固定存放空间方式。动态存放方式:则是在程序运行期间依据需要进行动态分配存放空间方式。这个存放空间能够分为三部分:1.1.程序区程序区 2.2.静态存放
36、区静态存放区 3.3.动态存放区动态存放区程序区静态存放区动态存放区全局变量、局部静态变量形参变量局部动态变量(autoregister)函数调用现场保护和返回地址等第81页变量和函数有两个属性:数据类型数据类型和数据存放类数据存放类别别。存放类别指是数据在内存中存放方式。存放方式分为两大类:静态存放类和动态存放类。包含:自动(自动(auto);了解);了解静态(静态(static););重点重点存放器(存放器(register);了解);了解外部(外部(extern)。了解了解依据变量存放类别,能够知道变量作用域和生存期。第82页2 auto2 auto变量变量自动变量auto:不专门申明为
37、static存放类别局部变量都是动态分配存放空间,在调用该函数时系统会给它们分配存放空间,在函数调用结束时就自动释放这些存放空间。所以这类局部变量称为自动变量。函数中形参和在函数中定义变量(包含在复合语句中定义变量),都属这类。自动变量用关键字auto作存放类别申明。比如:比如:int(int)*定义f函数,为形参*auto int,;/*定义、为自动变量*第83页3 3 用用externextern申明外部变量申明外部变量(略)略)外部变量是在函数外部定义全局变量,它作用域是从变量定义处开始,到本程序文件末尾。在此作用域内,全局变量能够为程序中各个函数所引用。编译时将外部变量分配在静态存放区
38、。用extern来申明外部变量,以扩展外部变量作用城。第84页4 Static4 Static静态变量静态变量主要讲局部静态变量当函数中局部变量值在函数调用结束后不消失而保留原值时,该变量称为静态局部变量。用关键字static进行申明。第85页例例621考查静态局部变量值#includevoidmain()int(int);int,;for(;printf(,();int(int)autoint;static;return();第86页对静态局部变量说明:对静态局部变量说明:(1)静态局部变量属于静态存放类别,在静态存放区内分配存放单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)
39、属于动态存放类别,占动态存放区空间而不占静态存放区空间,函数调用结束后即释放。(2)对静态局部变量是在编译时赋初值,即只赋初值一次,在程序运行时它已经有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时值。第87页 若希望函数若希望函数调用结束后,其值不消失调用结束后,其值不消失,下次调用函数时继续使用,则,下次调用函数时继续使用,则用用staticstatic对变量加以申明。对变量加以申明。例例 考查静态局部变量值考查静态局部变量值 f(int a)f(int a)auto int b=0;auto int b=0;static int c=3;static int c=3;
40、b=b+1;c=c+1;b=b+1;c=c+1;return(a+b+c);return(a+b+c);main()main()int a=2,i;int a=2,i;for(i=0;i3;i+)printf(“%d ”,f(a);for(i=0;i3;i+)printf(“%d ”,f(a);运行结果:运行结果:7 8 9第88页(3)如在定义局部变量时不赋初值话,则对静态局部变量来说,编译时自动赋初值(对数值型变量)或空字符(对字符变量)。而对自动变量来说,假如不赋初值则它值是一个不确定值。(4)即使静态局部变量在函数调用结束后依然存在,但其它函数不能引用它。第89页例例621输出到阶乘值
41、#includevoidmain()intfac(int);int;for(;)printf(%!=,fac();Intfac(int)staticint;*;return();第90页(年9月全国计算机等级考试二级笔试原题)第91页年年3月全国计算机等级考试二级笔试试卷月全国计算机等级考试二级笔试试卷C语言程序设计试题语言程序设计试题D第92页5 register5 register变量(略)变量(略)变量值是存放在内存中。当程序中用到哪一个变量值时,由控制器发出指令将内存中该变量值送到运算器中。经过运算器进行运算,假如需要存数,再从运算器将数据送到内存存放。第93页 假如有一些变量使用频繁
42、,则为存取变量值要花费不少时间。为提升执行效率,语言允许将局部变量值放在CPU中存放器中,需要用时直接从存放器取出参加运算,无须再到内存中去存取。因为对存放器存取速度远高于对内存存取速度,所以这么做能够提升执行效率。这种变量叫做存放器变量存放器变量,用关键字registerregister作申明。第94页例622使用存放器变量#includevoidmain()longfac(long);longi,n;scanf(%ld,&n);for(i=1;i=n;i+)printf(%ld!=%ldn,i,fac(i);longfac(longn)registerlongi,f=1;/*定义存放器变量*/for(i=1;i=n;i+)f=f*i;return(f);第95页