




已阅读5页,还剩85页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
共90页第1页,第八章,C语言程序设计,函数,共90页第2页,本章要点函数的定义函数的调用函数间的数据传递变量的存储类型变量的作用范围内部函数和外部函数,共90页第3页,C程序是函数的集合体,每个函数是一个独立的程序模块。有一个主函数,若干个子函数,程序总是从主函数开始执行。函数可集中或分散存放在一个或多个源程序文件中。所有子函数地位平等,可互相调用、自我调用。引入函数的优点:减少重复编写程序的工作量;使程序便于调试和阅读。,函数,C语言程序的结构,8.1函数的概念和函数的定义,共90页第4页,数学函数math.h字符和字符串函数ctype.h,string.h输入/输出函数stdio.h动态存储分配函数calloc(),malloc(),C函数的分类,共90页第5页,例输入三个整数,计算它们的和并输出运算结果。,intadd(intx,inty,intz)ints;s=x+y+z;returns;,函数示例,定义的求和函数,main()inta,b,c,sum;scanf(%d,%d,%d,调用求和函数,共90页第6页,8.1.2函数的定义,定义函数应包括的内容:(1)指定函数的名字,以便以后按名调用;(2)指定函数的类型,即函数值的类型;(3)指定函数的参数的名字和类型(有参);(4)指定函数执行的操作,即函数完成的功能。,在程序中用到的所有函数,必须先定义,后使用。,共90页第7页,定义函数的一般形式类型标识符函数名(形式参数表)说明部分语句,共90页第8页,1.无参函数的定义形式类型标识符函数名()说明部分语句,例8-1voidprint_message()printf(Howareyou!n);,共90页第9页,例8-2intmax(intx,inty)intz;z=xy?x:y;returnz;,类型标识符函数名(形式参数表列)说明部分语句,intmax(x,y)intx,y;intz;z=xy?x:y;returnz;,形参变量的说明(传统形式),形参变量的说明(现代形式),2.有参函数的定义形式,共90页第10页,3.形式参数说明形式参数:在定义函数时函数名后面括弧中的变量名在形参表中说明的形参,在函数体中不再说明,可以同一般变量一样直接使用。形参调用前不占内存单元,调用时分配内存单元。调用结束后释放。形参是函数的内部变量,只在函数内部才有意义。对每个形参必须指明其名字和数据类型。多个形参用逗号分隔。,共90页第11页,例:有函数调用语句:inti=3;printf(”%d,%d”,i,+i);输出结果为:4,4,分析输出函数的结果:自右向左:4,4自左向右:3,4,避免这种不确定性:改为:inti=3,j;j=i;printf(”%d,%d”,i,+j);输出结果为:3,4,共90页第12页,8.1.3函数的调用,1.函数调用的一般形式为:函数名(实际参数列表);或函数名(实际参数列表)说明:实参必须有确定的值,可以是常量、变量、表达式及函数调用。实参与形参的类型、个数、顺序必须一致。多个实参用逗号分隔。,2.执行过程:计算各个表达式(TC2.0,VC+6.0实参求值顺序按自右至左);把得到值赋给对应的形参;执行函数体;遇到return语句或执行完最后一条语句,返回到函数调用处.,共90页第13页,(1)函数语句:(把函数调用作为一个语句)一般形式:函数名(实际参数表);使用情况:这种方式常用于调用一个可以忽略返回值或没有返回值的函数,只要求函数完成一定的操作。例如:print_message();,3.函数调用的具体方式,(2)函数表达式:(函数调用出现在一个表达式中)一般形式:变量名=函数表达式使用情况:这种表达式称为函数表达式。要求函数带回一个确定的值参加表达式的运算。例如:c=3+max(a,b);d=pow(c,i);e=f(x1,x2,x3),(y1,y2);函数有几个参数?,共90页第14页,值传递:在函数调用时,实参将其值传递给形参。实参对形参的数据传递是“值传递”,即单向传递,只由实参传递给形参,而不能由形参传回来给实参。实参与形参占用不同的单元。在调用函数时,给形参分配存储单元,并将实参对应的值传递给形参,调用结束后,形参单元被释放,实参单元仍保留并维持原值。在执行一个被调用函数时,形参的值如果发生变化,并不会改变主调函数中实参的值。,8.1.4函数参数的传递方式,值传递的优点:被调用的函数不可能改变调用函数中变量的值,而只能改变它的局部的临时副本。,值传递的缺点:每个形式参数仅能传递一个数据,不适用需要在函数之间传递大量数据。,地址传递:将实参的地址传递给形参,实参和形参指向同一内存空间,对形参的修改,可以直接影响实参。,共90页第15页,例8-3编写函数交换两个变量的值。#includevoidswap(intx,inty)inttemp;temp=x;x=y;y=temp;printf(x=%d,y=%dn,x,y);intmain()inta,b;a=5;b=10;printf(a=%d,b=%dn,a,b);swap(a,b);printf(a=%d,b=%dn,a,b);,运行结果:a=5,b=10 x=10,y=5a=5,b=10,共90页第16页,8.1.5函数的返回值,2.函数的返回值语句一般形式:return表达式;或return(表达式);功能:退出函数,将表达式的值带回主调函数,回到程序原来的位置继续执行。return语句也可以没有表达式,其作用是使程序执行的流程返回到调用函数。,定义:通过函数调用使主调函数得到一个确定的值,称为函数的返回值。,共90页第17页,说明:return语句只能把一个返回值传递给调用函数。返回值的类型为定义的函数类型,若return语句中表达式类型与函数类型不一致,以函数类型为准。返回值可以是有确定值的常量、变量或表达式,也可以是地址。当返值是地址时,应该用指针接受。无返回值的函数,定义为void类型(无类型函数)。一个函数中可以有多个返回语句。exit()函数由ANSCC定义的,功能是终止和关闭所有程序,结束程序执行,忽略返回值。0为正常退出非0为非正常退出。,共90页第18页,main()inta,b,c;scanf(“%d,%d”,例8-4intmax(intx,inty)intz;z=xy?x:y;return(z);,形参:通知系统要预留内存位置.,实参:在运行时把值传给函数.,把函数的结果赋给函数名,形参与实参、函数名与返回值之间的关系,共90页第19页,例8-5用函数计算浮点数x的n次方,其中n为整型(n=0),doublepower(doublex,intn)doublep=1;inti;if(n0)for(i=1;i=0)putchar(stringi);,intmain()printf(Theconvertedstring:);to_str(-123);return0;运行结果:Theconvertedstring:-123,共90页第21页,例8-7编写函数,求1+1/2+1/3+1/n的值,并在主函数中调用它。#includedoublecount(intn)inti;doublesum=0;if(n=0)printf(Dataerror!n);return0;elsefor(i=1;i=n;i+)sum+=1.0/i;returnsum;intmain()intn;doubles;printf(Pleaseinputthevalue:);scanf(%d,运行结果:Pleaseinputthevalue:5s=2.28,共90页第22页,8.1.6函数的声明,问题的提出:C语言程序可由若干文件组成,每一个文件可以单独编译。一个源程序文件由一个或多个函数组成。在一个函数中调用另一个函数需要具备如下条件:1)函数必须是已经定义的函数;2)如果使用库函数,应该在文件开头包含库函数的信息;3)若函数使用在定义之前,必须在调用函数前对函数进行声明。,同变量一样,函数的调用也应该遵循“先说明,后使用”的原则。,1.函数声明的一般形式:类型标识符函数名(类型1形参1,类型2形参2,);功能:通知编译程序函数值类型、参数个数及类型,为编译程序进行类型检查提供依据。,共90页第23页,main()floatadd(floatx,floaty);floata,b,c;scanf(“%f,%f”,/*定义add函数*/floatadd(floatx,floaty)floatz;z=x+y;return(z);,对被调用函数的说明,作为表达式被调用,共90页第24页,2.函数声明和函数定义的区别,函数声明的作用是把函数的名字、函数类型以及形参的类型、个数和顺序通知编译系统,以便在调用该函数时系统按此进行对照检查。,函数定义是指对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的函数单位。,函数声明与函数定义的首部唯一区别:函数说明语句的()之后必须有分号,而函数定义头部的()之后没有分号。,共90页第25页,(1)被调用函数在主调函数之前定义,floatadd(floatx,floaty)floatz;z=x+y;return(z);main()floata,b;scanf(“%f,%f,“,3.可省略被调用函数声明的二种情况,共90页第26页,(2)在所有函数定义之前说明,charletter(char,char);floatf(float,float);inti(float,float);main().charletter(charc1,charc2)floatf(floatx,floaty)inti(float,float),在所有函数之前说明函数类型,定义函数letter、f和i,共90页第27页,8.2数组作函数参数,数组元素可以作函数的实参数组元素作为表达式的组成部分做函数的实参可以单向将值传递给形参。例如:inta10;x=power(a6,5);数组名可以作函数的实参和形参实现批量数据的传递,共90页第28页,一维数组作函数参数,形参的写法为:类型说明符形参数组名数组长度例如:floataverage(floatarray10)main()floatb10;inti;for(i=0;i10;i+)scanf(“%f”,8.2.1一维数组作函数参数,说明:形参和实参分别定义数组数组做函数参数时,实参用数组名,必须有确切值实参数组和形参数组类型应一致。,共90页第29页,说明:实参数组和形参数组大小不一定一致,一维形参数组可以不指定大小。数组名除作为变量的标识外,还代表该数组在内存中存放区域的首地址。数组名做函数实参与形参之间是“地址传递”,实参数组将数组的起始地址传递给形参数组。编译系统不再为形参数组分配存储单元。在函数体中对形参数组的元素操作时就是对实参数组的元素进行操作。形参数组各元素的值发生变化会使实参数组各元素的值发生同样的变化。数组名作函数参数可实现大量数据的传递,无须返回数组值。,共90页第30页,例8-8阅读如下程序,给出打印结果。voidswap(inta)intt;t=a0;a0=a1;a1=t;main()intb2=1,2;swap(b);printf(“b0=%d,b1=%dn”,b0,b1);,结果:,程序运行演示,可不定义长度,在调用函数过程中改变了原数组的值,实参数组与形参数组共享一组存储空间,,地址传递,共90页第31页,例8-9:编写函数用选择法对数组中10个整数由小到大排序.,程序设计思想:,函数sort(array,n):实现数组元素由小到大排序。,主程序:输入array数组,调用sort函数比较,输出排序后的array数组。,voidsort(intarray,intn)inti,j,k,t;for(i=0;in-1;i+)k=i;for(j=i+1;jn;j+)if(arrayjarrayk)k=j;if(k!=i)t=arrayk;arrayk=arrayi;arrayi=t;,用另外一个参数表示数组的长度,共90页第32页,main()inta10,i;printf(“enterarray:n”);for(i=0;i10;i+)scanf(“%d”,由于地址传递,实参数组a改变,数组名做参数的好处:,由于只需复制一个地址值,而无须复制全部需要处理的数据,因此节约存储空间并提高效率。,由于主调函数和被调函数是在相同的内存区域上对数据进行操作,因此可以实现数据的同步更新。,函数调用,共90页第33页,例8-10将给定字符串复制到另一字符串。#include“stdio.h”voidstrcopy(charstr1,charstr2)inti=0;while(str1i!=0)str2i=str1i;i+;str2i=0;main()chars150,s250;printf(“Inputstrings1:”);gets(s1);strcopy(s1,s2);printf(“%s”,s2);,共90页第34页,【例8-11】函数del(s,i,n)的功能是从字符串s中删除从第i个字符开始的n个字符。主函数调用del函数,从字符串management中删除从第3个字符开始的4个字符,然后输出删除子串后的字符串。voiddel(chars,inti,intn)intj,k,length=0;while(slength!=0)A;j=-i;k=i+n;while(klength)sj+=sk+;sj=0;main()charstr=management;del(B);printf(Thenewstringis:%sn,str);,答案A:length+B:str,3,4,共90页第35页,8.2.2二维数组作函数参数,二维数组作函数参数,形参的写法为:类型说明符形参名数组长度1数组长度2说明:形参数组定义时可以指定或省略第一维的大小例如:intarray310;或intarray10;intarray3;和intarray;错误,实参数组可以大于形参数组例如:实参数组定义为:intarray510;形参数组定义为:intarray310;这时形参数组只取实参数组的一部分,其余部分不起作用。,共90页第36页,例8-12编写函数,求3*4矩阵中的最大值。intmax_value(intarray4)inti,j,max;max=array00;for(i=0;imax)max=arrayij;return(max);intmain()inta34=1,3,5,7,2,4,6,8,10,12,15,17;printf(“max=%dn”,max_value(a);,共90页第37页,8.3函数的嵌套调用和递归调用,8.3.1函数的嵌套调用嵌套定义:在定义一个函数时,该函数体内包含另一个函数的定义。嵌套调用:在调用一个函数的过程中,又调用另一个函数。C语言不能嵌套定义,但可以嵌套调用!,共90页第38页,两层嵌套的例子,共90页第39页,8.3.2函数的递归调用,f函数,调用f函数,1.递归的概念:在调用一个函数的过程中直接或间接地调用该函数本身。直接调用:intf(x)intx;inty,z;z=f(y);return(2*z);,共90页第40页,intf1(x)intx;inty,z;.z=f2(y);return(2*z);,intf2(t)intt;inta,c;.c=f1(a);return(3+c);,间接调用:,共90页第41页,递归函数的执行过程:-递归调用:记住本次现场,递归调用。-终了调用:返回上次调用现场。特点:-是无终止的递归调用,因此,应该给定一个限制递归次数的条件。-结构简练。,共90页第42页,floatfac(intn)floatf;if(n0)printf(“n1),例8-13用递归法求n!,不能赋给函数名,共90页第43页,递归函数fac的求解过程,以求9的阶乘为例:,fac(9)=9*fac(8),fac(8)=8*fac(7),fac(2)=2*fac(1),fac(1)=1,fac(9)=9*fac(8),fac(8)=8*fac(7),fac(2)=2*1,fac(3)=3*fac(2),fac(3)=3*2*1,下推,回代,共90页第44页,例8-14用递归法将一个整数n转换成字符串。例如输入256,应输出“256”,n的位数不固定,可以是任意位数的整数。,voidtranvers(intn)if(n/10!=0)tranvers(n/10);printf(%c,n%10+0);,main()intn;printf(“pleaseinputanintegralnumber”);scanf(%d,共90页第45页,共90页第46页,变量的数据类型,char型int型float型double型,总结:数据类型决定为变量分配的内存单元的长度,数据的存放形式。(从程序设计角度,决定了可以表示的数的范围),问题:1.何时为变量分配内存单元?2.变量位于内存的什么位置?3.变量的有效作用范围?,8.4变量的作用域和存储方法,(VC+6.0环境),共90页第47页,变量的作用域和生存期:变量的作用域指一个变量在程序中的有效范围。(也称为可见性)C语言规定:凡是在函数内定义的变量,它的作用域仅仅是包含这个变量定义的复合语句;而在函数体外定义的变量,它的作用域是从定义点到文件尾。变量的生存期指程序在执行期间,变量存在的时间间隔,即从给变量分配内存,至所分配内存被系统收回的那段时间。C语言规定:凡是出现在静态数据区的变量,生存期都是从程序开始执行到程序结束;而出现在静态区之外的变量,生存期仅仅是从函数开始执行到函数执行结束这段时间。,共90页第48页,1.局部变量(内部变量)定义:在函数内部定义的变量,只能在本函数内部使用。说明(避免了函数间的相互干扰,增加了函数的独立性)主函数main定义的变量只在主函数中有效,主函数不能使用其它函数定义的变量。不同函数可以使用相同名字的变量。形式参数也是局部变量。可以在一个函数内部,也可以在复合语句中定义变量,这些变量只在本复合语句中有效。,8.4.1局部变量和全局变量,charsearch(chars)charch;intk;,变量s、ch、k的作用域,编译系统不为局部变量分配内存单元,只是当被调用时,根据需要分配临时单元,调用结束,空间释放。,共90页第49页,例:main()intm,n;intx,y;,共90页第50页,阅读以下程序,写出程序的运行结果。main()inti=3,j=2,k;k=i+j;intk=8;if(i=4)printf(%d,k);elseprintf(%d,j);printf(%d,%d,i,k);,2,3,5,共90页第51页,2.全局变量定义:在函数之外定义的变量是全局变量(外部变量)。语法:类型说明变量名;使用范围:可以为本文件中所有的函数公用。从定义变量的位置开始到本文件结束,这段程序中的函数可直接使用全局变量,,inta,b=3;main()floatk;charstr(chars20),全局变量a、b的作用域,全局变量k的作用域,共90页第52页,intp=1,q=5;/*外部变量*/f1(inta)/*定义函数*/intb,c;charc1,c2;/*外部变量*/f2(inta,intb)/*定义函数*/.main()intm,n,全局变量c1、c2的作用范围,全局变量p、q的作用范围,共90页第53页,例如:#include“stdio.h”inta=7,b=10;main()inta=5,c;c=a+b;printf(“c=%dn”,c);,在同一源文件中,全局变量和局部变量可以同名,在局部变量的作用范围内,全局变量不起作用。,C=15,全局变量,局布变量,局部变量,全局变量,共90页第54页,优点:函数间数据联系:同一文件中的一些函数引用全局变量,当某个函数中改变了全局变量的值,其它函数中的全局变量值也随之改变。函数可以得到多个返回值。(在所有函数之外说明的变量是全局变量,它在所有函数中都是可见的。利用全局变量的这个特性,可以在函数间传递数据。)缺点:全局变量在程序的全部执行过程中都占用存储单元。降低函数的通用性。使用过多,降低程序的清晰性。全局变量应尽可能少用。,共90页第55页,例8-15编写函数,利用全局变量求一维数组中正数的平均值和负数的平均值传递给调用函数输出。,#includefloatzaver=0,faver=0;voidsaver(intarray,intn)inti,z=0,f=0;for(i=0;i0)zaver+=arrayi;z+;if(arrayi0)faver+=arrayi;f+;if(z!=0)zaver=zaver/z;if(f!=0)faver=faver/f;main()inta10=1,-3,4,6,-2,7,9,-8,-5,0;saver(a,10);printf(“正数平均值=%f,负数平均值=%fn”,zaver,faver);,共90页第56页,下面程序的运行结果是()。#include“stdio.h”intx1=30,x2=40;voidsub(intx,inty)x1=x;x=y;y=x1;main()intx3=10,x4=20;sub(x3,x4);sub(x2,x1);printf(“%d,%d,%d,%dn”,x3,x4,x1,x2);,答案10,20,40,40,共90页第57页,变量的存储类别静态存储方式:程序运行期间分配固定存储空间的方式。动态存储方式:程序运行期间根据需要进行动态的分配存储空间的方式。,8.4.2变量的存储方法,共90页第58页,动态存储变量特点函数开始调用时为变量分配存储空间,函数结束时释放这些空间。一个程序两次调用同一函数,其中同一个局部变量的内存地址可能不同。静态存储变量特点在静态存储区分配存储单元,整个程序运行期间都不释放。,变量存贮类型有四种:自动变量(auto)静态变量(static)外部变量(extern)寄存器变量(register)auto、static、extern和register为存贮类型说明符。,共90页第59页,(1)自动变量(auto)函数中的局部变量,不做任何存储类别的说明都为自动变量。定义形式:auto类型说明符变量名;说明:“auto”可以省略。以前所使用的全部变量都是自动变量。自动变量必须在一个函数体的内部。函数的形参也是自动变量。例如:intb,c=3等价于autointb,c=3;作用域:包含变量定义的复合语句或所说明的函数内部;在函数被调用时才存在,从函数中返回时即消失,值也仅限于说明它的函数,在其它的函数中不能存取,在两个不同的函数中可以分别使用同名的变量。,1.局部变量的存储方法,共90页第60页,(2)局部静态变量定义形式:在变量名前面加关键字staticstatic类型说明符变量名;局部静态变量编译时赋初值,每次调用时不赋初值,只保留调用结束时变量的值。如果不赋初值,编译时自动赋0值。局部静态变量只允许所在函数引用,其它函数不能引用。其值整个程序运行期间都不释放。自动变量不赋初值,其值不确定。每调用一次,重新赋值一次。,共90页第61页,例如:intf(inta)intb=0;staticintc=3;b=b+1;c=c+1;return(a+b+c);main()inta=2,i;for(i=0;i3;i+)printf(“%d,”,f(a);,运行结果为:7,8,9,第一次调用开始,第一次调用结束,第二次调用开始,0,b,3,4,4,1,0,c,共90页第62页,例如:,#include“stdio.h”intfun(intx,inty)staticintm=0,i=2;i+=m+1;m=i+x+y;returnm;main()inta=2,b=3;printf(%d,fun(a,b);printf(%dn,fun(b,a);,8,17,运行结果:,共90页第63页,(3)寄存器变量(register)直接放置在运算器的寄存器中的变量称为寄存器变量.定义形式:register类型说明符变量名;作用:对于使用频繁的变量,定义为寄存器变量,不必从内存而是直接从寄存器中取出参加运算,提高程序执行效率。说明:只有局部自动变量和形式参数可作为寄存器变量,其它如局部静态变量和全局变量不可以。属于动态存储方式,函数开始调用时为变量分配寄存器空间,函数结束时释放寄存器空间。只有int、char和指针类型可定义为寄存器变量,而long、double和float型变量不能设定为寄存器型。可用于变量空间分配的寄存器个数依赖于具体的机器。通常为2到3个,若在一个函数中说明多于2到3个寄存器变量,编译程序会自动地将它们变为自动变量。,共90页第64页,2.全局变量的存储类型(外部全局变量、静态全局变量)(1)外部全局变量在多个源程序文件的情况下,如果在一个文件中要引用在其它文件中定义的全局变量,则应该在需要引用此变量的文件中,用extern做说明。例如:,prog1.c的内容如下:inta;main()x=6;f1();voidf1()a+=2;printf(a=%dn,a);f2();,prog2.c的内容为:externinta;voidf2()a+;printf(a=%dn,a);,共90页第65页,(2)静态全局变量在一个文件中定义的全局变量仅限于本文件引用,而不能被其它文件访问,则可以定义为静态全局变量。例如:staticintx;说明:外部全局变量与静态全局变量在同一文件内的作用域一样外部全局变量可以被多个文件引用,而静态全局变量仅在定义它的文件内有效,在程序的其它文件中不可使用。例如:file1.cfile2.cstaticinta;externinta;staticinta只能用于file1.c,虽然file2.c中将同名变量inta说明为extern,但仍无法使用file1.c中的a变量。,共90页第66页,8.5内部函数和外部函数,1.内部函数(静态函数)定义:如果一个函数只能被本文件中其它函数调用,称为内部函数。定义格式:static类型标识符函数名(形参表)函数体例如:staticintfun(a,b)作用:函数的作用域限于所在文件,不同文件中同名函数互不干扰,便于程序的格式化。,共90页第67页,2.外部函数定义:如果一个函数允许被其它文件调用,称为外部函数。定义格式:extern类型标识符函数名(形参表)函数体例如:externintfun(inta,intb)或intfun(inta,intb)通常不加static标识符的函数都是外部函数。,共90页第68页,3.标号的生存期及作用域生存期在C语言中,由于函数的生存期是全程的,即从程序开始至程序结束,标号是函数的一部分,标号的生存期自然是全程的。作用域C语言规定,标号的作用域仅为定义标号的函数,即不允许用goto语句从一个函数转向另一个函数。,共90页第69页,有关函数的类型,1函数的类型是函数返回值的类型2C要求函数定义的类型,说明的类型和函数定义类型一致3定义的类型与返回值类型不一致时,以定义为准4不定义函数类型,系统默认是int。(VC+6.0必须指定函数类型)5不需返回任何返回值时,应定义无类型void。,总结,共90页第70页,有关函数的参数,1定义函数时,括号内为形参2调用函数时,括号内为实参3实参与形参需类型相同,个数相等4形参在函数被调用时才分配存储空间,有值5实参在主调函数内有值,求值顺序是从右向左6实参与形参是单向的数值传递7如果实参与形参都是数组名,是地址传递8实参数组与形参数组类型相同,个数可以不同,函数间的数据传递(三种传递方式):返回值、参数、全局变量。,共90页第71页,1函数可以作运算分量,作其他函数的参数,可构成语句2函数调用可以嵌套3函数中的return语句可以带回一个返回值,有关变量,从变量的作用域:局部变量全局变量从变量值保留的期限:静态存储变量动态存储变量从变量在硬件上的位置:CPU寄存器内存中静态区内存中动态区,有关函数的调用,共90页第72页,存储特性,共90页第73页,file1.c程序:intplus(intx,inty)intz;z=x+y;returnz;,例:现已定义函数plus求两个数的和,包含在文件file1.c中,在file2.c程序文件中要调用此函数,请将下列程序补充完整,使程序正确。,file2.c程序:#include_A_main()inta=4,b=5,c;_B_plus(int,int);c=plus(a,b);printf(“a+b=%d”n”,c);,答案A:“file1.c”B:extern,共90页第74页,例下面程序由两个文件组成,请分析运行结果。,/*文件一prog1.c*/#includestdio.h#includeprog2.cintx=10,y=10;externvoidsub();voidadd()inty=5;y=10+x;x*=2;printf(add:y=%d;,y);main()x+=5;add();sub();printf(main:x=%d;main:y=%dn,x,y);,/*文件二prog2.c*/#include“stdio.h”externintx;voidsub()inty=5;x-=y;printf(“sub:y=%d;”,y);,运行结果:,共90页第75页,C的源程序预处理编译目标程序(*.C)_(*.OBJ),编译系统中有:预处理程序编译程序,宏替换#defineN20文件包含#include条件编译#if(.),C中的预处理命令分类,8.6编译预处理,共90页第76页,宏定义有两种类型:字符串替换和带参数的宏替换,(1)字符串宏替换,功能:在预处理时,将程序中宏定义之后出现的所有的宏名,用宏替换体代替。,宏替换名,宏替换体,例如:#definePI3.14159,格式:#define宏名宏定义字符串,C的编译程序调用预处理程序检查有否宏名,若有,用宏替换体将其替换,完成之后,将替换后的源程序交给编译程序。,1.宏定义,共90页第77页,用途:提高程序的可读性,便于修改、调试。,-符号常量,如PI、数组的长度-为程序书写带来方便(将程序中多次出现相同内容写成宏),#defineN10/*编译之前用10替换所有的N*/.intaN,说明:,通常放在程序开头,不加分号,是代替,不是赋值(不作语法检查),可将多个语句或表达式定义为一个宏替换,为区别变量和关键字,习惯用大写,共90页第78页,#defineR3.0#definePI3.145926#defineL2.0*PI*R#defineSPI*R*R,双引号中的不替换,有效范围,从定义开始到程序结尾,例:#definePI3.14159main()printf(“PI=%fn”,PI);,结果:PI=3.14159,main()printf(“PI=%sn”,”PI”);,可以嵌套,后定义的宏可以包含先定义的宏名,结果:PI=PI,共90页第79页,(2)带参数的宏定义,带参数的宏不仅能进行字符串代替,而且还能进行参数代换。,格式:#define宏名(参数表)表达式,功能:,带参数的宏将一个带形参的表达式定义为一个带参数的宏名,预处理程序对程序中所有带实参表的宏名进行宏展开替换,用表达式代替宏名,用参数表中的实参代替表达式中对应的形参。,例:#defineS(a,b)a*b,程序中S(3,2),3*2,共90页第80页,用途:,用带参数的宏可以代表一些简短的表达式,提高程序执行的效率。,*对常用的格式输入输出函数printf可以进行宏定义,使程序简化,*宏名与参数的圆括号之间不能有空格s(a,b),说明:,*宏定义命令要求在一行内写完,如换行,用“”表示下一行继续。,*对于宏定义的形参要根据需要加上圆括号,以免
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论