版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第6章函数与编译预处理6.1函数概述6.2函数的定义和说明6.3函数的调用6.4函数的参数6.6变量的存储类型6.7内部函数和外部函数6.8编译预处理命令6.5函数的嵌套调用与递归调用
6.1函数概述
★函数是封装了一定功能的模块
★C语言是函数驱动式语言(一个源程序文件由一个或多个函数组成)#include“stdio.h”
voidmain(
)//函数头
{
inta=8;
printf(“a=%d”,a);
}
//函数体★一个C源程序必须有且只能有一个主函数main(
)。C程序总是从main(
)函数开始执行,最后结束于main(
)函数,其他函数是通过main(
)直接或间接调用完成其功能的。#include<stdio.h>intadd(intx,inty){ints;s=x+y;returns;}main(){inta=1,b=2,c;c=add(a,b);printf("%d\n",c);}kj61一、函数定义二、函数声明三、函数调用#include<stdio.h>main(){inta=1,b=2,c;
intadd(intx,inty);c=add(a,b);printf("%d\n",c);}intadd(intx,inty){ints;s=x+y;returns;}函数概述(1)一个C程序由一个或多个源(程序)文件组成——可分别编写、编译和调试。(2)一个源文件由一个或多个函数组成,可为多个C程序公用。(3)C语言是以源文件为单位而不以函数为单位进行编译的。(4)在C语言中,所有函数(包括主函数main(
))都是平行的。一个函数的定义,可以放在程序中的任意位置,主函数main(
)之前或之后。但在一个函数的函数体内,只能调用其他函数,不能再定义另一个函数,即不能嵌套定义。(5)主函数名main是系统定义的,是运行时首先被调用的函数,它可以调用其他函数,但不能被其他函数调用;其他函数间可以互相调用,也允许嵌套调用。(6)从函数定义的角度看,函数可分为库函数和用户定义函数两种。①库函数:由C系统提供,用户无须定义,也不必在程序中进行类型说明,只需在程序前写出包含有该函数原型的头文件即可在程序中直接调用。在前面各章的例题中反复用到的printf(
)、scanf(
)、getchar(
)、putchar(
)、gets(
)、puts(
)等函数均在头文件stdio.h中,sqrt(),fabs(),pow()等函数均在头文件math.h中。②用户定义函数:由用户按需要编写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且还必须在主调函数模块中对该被调函数进行类型说明,然后才能使用。(7)从主调函数和被调函数之间数据传送角度看,函数又可分为无参函数和有参函数两种。(8)C语言的函数兼有其他语言中的函数和过程两种功能,从这个角度看,又可把函数分为有返回值函数和无返回值函数两种。6.2.1函数定义C语言函数定义格式如下:[函数返回值的类型名]函数名([类型名形式参数1,类型名形式参数2,…])/*函数头*/{[说明部分;]/*函数体*/[语句部分;]}其中[]内为可选项。注意:函数名、一对圆括号和花括号不能省!6.2函数的定义和说明1.无参函数无参函数的一般形式函数返回值的类型名函数名(void){[说明语句部分;][可执行语句部分;]}例:
构造一个输出一行”*”的函数:voidprintstar(void){printf(“******************\n”);}
kj622.有参函数例:编写函数交换2个数;kj63voidswap(inta,intb){inttemp;temp=a;a=b;b=temp;}
不能写成:voidswap(inta,b){inttemp;temp=a;a=b;b=temp;}函数返回值类型函数名参数类型说明及参数列表6.2.2函数的返回值函数分为有返回值函数和无返回值函数。return语句的格式:return(表达式);或return表达式;或return;功能:1、把return后面“表达式”的值带给调用函数;
2、把控制转向调用函数;格式return;只有功能2例:编写函数,返回2个整数的最大公约数。(辗转相除法)kj64
intf(intx,inty){intr,t;if(x<y){t=x;x=y;y=t;} while((r=x%y)!=0) {x=y;y=r;}returny;}
注意:(1)声明为为void型的函函数中中不能能包括括带值值的return语句;;主函函数体体内一一般不不用return语句。。(2)当函数数没有有return语句时时,以以结束束函数数的大大括号号}作为返返回点点。但但这时时并不不表明明函数数没有有返回回值,,这时时的返返回值值是系系统给给的不不确定定值。。(3)在同一一函数数内,,可根根据需需要在在多处处出现现return语句,但但函数第第一次遇遇到return时就立即即停止执执行,并并返回到到主调函函数;(4)return语句中返返回值表表达式的的类型应应该和函函数类型型一致。。如果不不一致,,则以函函数类型型为准,,由系统统自动进进行转换换。如果果缺省函函数类型型,则系系统一律律按int类型处理理。intf(chars1,chars2){if(s1==s2)return1;return0;}kj65例:计算两数数之和#include<stdio.h>doubleadd(doublex,doubley){doubles;s=x+y;returns;}main(){doublea,b,c;a=10.5;b=20.3;c=add(a,b);printf("%lf",add(a,b));add(a,b);}Kj66运行结果果为:30.8改成:intadd(doublex,doubley)?6.2.3函数说明明1.函数说说明的形形式函数说明明也称为为函数声声明,使使用函数数说明语语句能够够让C编译程序序了解函函数返回回值类型型被调用函函数说明明一般格格式如下下:函数类型型函函数名(数据类型型[参数名1][,数据类型型[参数名2]…]);函数说明明语句其其实就是是函数定定义中的的函数首首部加上上分号,,这些内内容称为为函数原原型。如:doublemax(doublex,doubley);voidswap(inta,intb);例:计算两数数之和#include<stdio.h>main(){doublea,b,c;a=10.5;b=20.3;c=add(a,b);printf("%lf",add(a,b));add(a,b);}doubleadd(doublex,doubley){doubles;s=x+y;returns;}kj67doubleadd(doublex,doubley);doubleadd(doublex,doubley);注意:有三种情情况不需需说明::a、函数返回值值为整型或字字符型;b、被调用函数数定义出出现在主主调函数数之前;;c、已在所有的的函数定定义之前前(即文文件的开开头)说说明了函函数类型型。6.3函数的调调用1、调用形形式:函数名((实参表表列);;实参与形形参个数数相等,,类型一一致。调调用函数数时两者者按顺序序一一对对应传递递数据。。main(){inta=1,b,f(int,int);b=f(a,++a);printf("%d",b);}intf(intx,inty){intz;if(x>y)z=1;elseif(x==y)z=0;elsez=-1;return(z);}例:参参数求求值顺序序main(){inta=1,b,f(int,int);b=f(a,a++);printf("%d",b);}intf(intx,inty){intz;if(x>y)z=1;elseif(x==y)z=0;elsez=-1;return(z);}运行结果果:0运行结果果:12、调用方方式:按函数在在程序中中出现的的位置来来分有三三种方式式。①函数数语句。。只完成一一个操作作,并不不要求函函数带回回值。如:printstar();scanf(““%d””,&a);②函数表达达式。出现在表表达式中中,函数数值参与与表达式式运算。。如:c=2*max(a,b);y=x+power(x,3);③函数参数数。函数调用用作为一一个函数数的实参参。如:m=max(a,max(b,c));printf(“%8.2f\n””,power(x,3));课堂练习习:下面程序序的输出出结果是是())。。#include<stdio.h>func(inta,intb){intc;c=a+b;returnc;}main(){intx=6,y=7,z=8,r;r=func((x--,y+=2,x+y),z);printf("%d\n",r);}A.11B.20C.21D.22课堂练习习:若有以下下函数调调用语句句:fun(a+b,(x,y),fun(n+k,d,(a,b)));fun函数参数数的个数数是A)3B)4C)5D)66.4函数的参参数形参与实实参形式参数数:定义义函数时时函数名名后面括括号中的的变量名名。实际参数数:调用用函数时时函数名名后面括括号中的的表达式式。例:编写程序序实现从从两整数数中求较较大数。。#include<stdio.h>floatmax(floatx,floaty);/*函数说明明*/main(){floata,b;floatc;scanf("%f,%f",&a,&b);c=max(a,b);/*调用函数数语句,a,b为实参*/printf("a=%f,b=%f\nmax=%f\n",a,b,c);}floatmax(floatx,floaty)/*函数定义义,x,y为形参*/{floatz;z=x>y?x:y;printf(“x=%f,y=%f\nz=%f\n””,x,y,z);return(z);}xy形参ab实参说明:实参必须须有确定定的值,形参必须须指定类类型形参与实实参类型型一致,,个数相相同若形参与与实参类类型不一一致,自自动按形形参类型型转换——函数调用用转换值传递方方式形参在函函数被调调用前不不占内存存;函数调用用时,为形参分分配单元元,并将实参参的值复复制到形形参中;;调用结结束,形形参单元元被释放放,实参参单元仍仍保留并并维持原原值特点:形参与实实参占用用不同的的内存单单元单向传递递例:计计算x的立方#include<stdio.h>floatcube(floatx){return(x*x*x);}main(){floata,product;scanf("%f",&a);product=cube(a);printf(”%.4f%.4f\n",a,product);}xaproduct××××1.21.21.7281030x:y:调用前:调用结束:1030x:y:例:交交换两两个数#include<stdio.h>main(){intx=10,y=30;printf("%d,%d\n",x,y);printf("swapped:\n");swap(x,y);printf("%d,%d\n",x,y);}swap(inta,intb){inttemp;temp=a;a=b;b=temp;}调用:1030a:b:1030x:y:swap:1030x:y:3010a:b:temp一般函数数调用main()调用函数a结束a函数执行2134566.5函数的嵌嵌套调用用和递归归调用6.5.1函数的嵌嵌套调用用函数的嵌嵌套调用用是指,,在执行行被调用用函数时时,被调调用函数数又调用用了其它它函数。。这与其其它语言言的子程程序嵌套套调用的的情形是是类似的的,其关关系可表表示如右右图所示示。例:求三个数中中最大数和和最小数的的差值intmax(intx,inty,intz)/*定义函数max求x,y,z中最大值*/{intr;r=x>y?x:y;return(r>z?r:z);}intmin(intx,inty,intz)/*定义义函函数数min,求x,y,z中最最小小值值*/{intr;r=x<y?x:y;return(r<z?r:z);}intdif(intx,inty,intz)/*定义义函函数数dif*/{returnmax(x,y,z)-min(x,y,z);/*嵌套套调调用用*/}voidmain(){inta,b,c,d;scanf("%d%d%d",&a,&b,&c);d=dif(a,b,c);/*调用用函函数数dif*/printf("Max-Min=%d\n",d);}若输输入入2、3,求求以以下下程程序序的的运运行行结结果果,,分分析析嵌嵌套套调调用用的的执执行行过过程程。。#include<stdio.h>intf(intn){intrtn=0;inti;for(i=1;i<=n;i++)rtn*=i;return(rtn);}longsum(inta,intb){longc1,c2;c1=f(a);c2=f(b);return(c1+c2);}main(){intn1=5,n2=10,a;a=sum(n1,n2);printf("a=%d",a);}6.5.2函数数的的递递归归调调用用在调调用用一一个个函函数数的的过过程程中中又又出出现现直直接接或或间间接接地地调调用用该该函函数数本本身身,,称称为为函函数数的的递递归归调调用用。。递归归调调用用形形式式如如下下:(1)直接接递递归归voida(){...……a();/*自己己调调用用自自己己,直接接递递归归*/...……}函数数a()调用用函函数数a()(2)间接接递递归归voida(){...……b();/*调用用函函数数b*/...……}voidb(){......a();/*调用用函函数数a,间接接递递归归*/………}调b调aa()b()以上上是是无无终终止止的的函函数数调调用用,,因因此此,,一一个个正正确确的的递归归调调用用的的函函数数必必须须满满足足以以下下条条件件::1、一一个个问问题题转转化化成成一一个个新新问问题题,,解解题题方方法法相相似似,,只只是是所所处处理理的的对对象象的的值值有有规规律律的的递递增增或或递递减减。。2、可以以应用用这个个转换换过程程使问问题得得到解解决。。3、必须须有明明确的的结束束递归归的条条件;;分析问问题2种方法法:递递推和和递归归递推::从一个个已知知的事事实出出发,,按一一定的的规律律推出出下一一个事事实。。通常利利用迭迭代公公式法法,通通过循循环结结构实实现,,循环环的终终值是是问题题的结结果。。递归::从要求求的结结果出出发,,归纳纳出后后一个个结果果和前前一个个结果果存在在的关关系,,直到到一个个已知知值为为止((即反反推法法)。。通常设设计函函数((递归归函数数),,不断断使用用下一一级值值调用用自身身,直直到一一个已已知的的值((递归归出口口)。。0!=11!=0!*1………………….n!=(n-1)!*n例:求求n的阶乘乘n!递推公公式::1n=0sn=sn-1*nn>0程序段段为::#include<stdio.h>main(){intm=1,i,n;scanf("%d",&n);for(i=1;i<=n;i++)m=m*i;printf("theresultis%10d",m);}例:求求n的阶乘乘n!递归方方法求求n!由于n!=n*(n-1)!是递归归定义义所以求求n!(n-1)!(n-1)!(n-2)!(n––2)!(n-3)!……1!0!的问问题,,已已知条条件为为:0!=1。递归函函数::1n=0f(n)=f(n-1)*nn>0递归函函数一一般形形式::函数名名f(参数数){if(n==初值))结结果=….;else结果=含f(n-1)的表达达式;return(返回结结果);}#include<stdio.h>intf(intx){intt;if(x==0)t=1;/*递归出出口*/elset=f(x-1)*x;;/*递归公公式*/return(t);}main(){intn=0,s;scanf("%d",&n);s=f(n);printf("%d!=%10d",n,s);}f函数在在回推推阶段段被调调用了了4次次,递递归调调用了了3次次,到到终止止条件件才有有确定定的值值,然然后再再递推推出每每一次次调用用的值值,最最后得得到所所求的的结果果。例::求求Fibonacci数列::打印1,1,2,3,5,8,………的的前40个个数。#include<stdio.h>main(){longf1,f2;inti;f1=1;f2=1;for(i=1;i<20;i++){printf("%12ld%12ld",f1,f2);if(i%2==0)printf("\n");f1=f1+f2;f2=f2+f1;}}方法1:用循循环结结构来来实现现#include<stdio.h>intfib(intn){intf;if(n==1||n==2)f=1;elsef=fib(n-1)+fib(n-2);returnf;}main(){inti;for(i=1;i<=40;i++){printf("%15d",fib(i));if(i%4==0)printf("\n");}}方法2:用递递归函函数来来实现现例:反向输输出一一个整整数#include<stdio.h>main(){intn;scanf("%d",&n);if(n<0){n=-n;printf("-");}while(n!=0){printf("%d",n%10);n=n/10;}}方法1:用循循环结结构来来实现现#include<stdio.h>voidmain(){voidprintn(intx);intn;scanf("%d",&n);if(n<0){n=-n;putchar('-');}printn(n);}voidprintn(intx)/*反向输输出整整数x*/{if(x>=0&&x<=9)/*若x为一位位整数数*/printf("%d",x);/*则输出出整数数x*/else/*否则*/{printf("%d",x%10);/*输出x的个位位数字字*/printn(x/10);/*将x中的个个位数数字去去掉,,形成成新的的x后,继继续递递归操操作*/}}方法2:用递归归函数来来实现输出一个个正整数数的递归归算法为为:if(n为一位整整数)输出n;else{输出n的个位数数字;对剩余数数字组成成的新整整数重复复"反向输出出"操作;}例:汉汉诺塔问问题。初始状态态:有3个塔,每每个都堆堆放若干干个盘子子。开始始时,所所有盘子子均在塔塔a上,并且且,盘子子从上到到下,按按直径增增大的次次序放置置。要求解决决问题::设计一个个盘子移移动的序序列,使使得塔a上的所有有盘子借借助于塔塔b移动到塔塔c上。两个限制制:1)一次只只能移动动一个盘盘子;2)任何时时候都不不能把盘盘子放在在比它小小的盘子的的上面。。假设塔塔a有n个盘子已知条件件:若只有一一个盘子子,则是是直接从从1移到到3(递归出出口)算法设计计如下::第一步::把n-1个盘子依依照题目目中的规规则从塔塔a(源塔))借助于于塔c(中间塔塔)搬到到塔b(目标塔塔)。第二步::将剩下下的一只只盘(也也就是最最大的一一只)直直接从塔塔a(源塔))搬到那那个仍然然空着的的塔c(目标塔塔)。第三步::再次将将b塔(源塔塔)上的的n-1个盘子借借助于塔塔a(中间塔塔)搬到到塔c(目标塔塔)。这这一步是是没有问问题的,,因为c塔上仅有有一只最最大的盘盘。函数hanoi(intn,inta,intb,intc)设计:1.如果果(n==1)则ac;2.否则执行行3步2-1调用函数数hanoi(n-1,a,c,b);2-2ac;2-3调用函数数hanoi(n-1,b,a,c);例Hanoi问题#include<stdio.h>voidhanoi(intn,inta,intb,intc){if(n==1)printf("%d->%d\n",a,c);else{hanoi(n-1,a,c,b);printf("%d->%d\n",a,c);hanoi(n-1,b,a,c);}}main(){intn;printf("Inputn:");scanf("%d",&n);hanoi(n,1,2,3);}运行情况况如下::inputn:3↙↙thestep:1-->31-->23-->21-->32-->12-->31-->3先看一个个例子,错在那里里?:#include"stdio.h"voidf1(){intt=2;a*=t;b/=t;}main(){inta,b;scanf("%d,%d",&a,&b);f1();//调用函数数f1()printf("a=%d,b=%d",a,b);}1编译程序序会提示示出错:Undefinedsymbol‘a’和Undefinedsymbol‘b’。为什么?6.6变量的存存储类型型6.6.1变量的生生存期和和作用域域生存期:变量在在某一时时刻存在在-------静态变量量与动态态变量作用域:变量在在某区域域内有效效-------局部变量量与全局局变量(文件、函函数、复复合语句句)6.6.2变量的存存储类型型(特性)1.c语言中每每一个变变量有两两个属性性:数据类型型,存储类型。完整的变变量定义义:[存储类型][数据类型型]变量名;2.变量的存存储类型(特性)自动型auto静态型static寄存器型型register外部型extern程序区静态存储区动态存储区2.静态存储储类型的变变量的生生存期为为程序执执行的整整个过程程,在该该过程中中占有固固定的存存储空间间,称它它们为永久存储储。staticextern动态存储储类型变量量只生存在在某一段段时间内内。例如,,函数的的形参和和函数体体内定义义的变量量,只是在程程序进入入该函数数时才分分配存储储空间,当该函数数执行完完后,变量对应应的存储储空间又又被撤销销了。atuoregister局部变量与全全局变量局部变量---内部变量定义:在函数内或复合语句定义说明:main(函数)中定义的变量量只在main(函数)中有效。复合语句中定义的变量量只在复合语句中有效。不同函数中同同名变量,占占不同内存单单元。形参属于局部部变量。局部变量可用用存储类型:autoregister。static(默认为auto)floatf1(inta){intb,c;…….}charf2(intx,inty){inti,j;……}main(){intm,n;…….}a,b,c有效x,y,i,j有效m,n有效#include<stdio.h>sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}main(){autointa,b;a=3;b=4;sub();printf("main:a=%d,b=%d\n",a,b);}31.自动变量量局部静态变量量值具有可继继承性局部静态变量量的初始化只只在编译时进进行一次,每次调用他们们所在的函数数时,不再重重新赋初值;;如定义但不初初始化,自动动赋0或‘‘\0’1.静态局部部变量static数据类型变变量名staticinti=1;#include<stdio.h>main(){voidin(void);in();in();in();}voidin(void){intx=0;x++;printf(“%d\n”,x);}4运行结果:111#include<stdio.h>main(){voidin(void);in();in();in();}voidin(void){staticintx=0;x++;printf(“%d\n”,x);}5运行结果::1231.静态局局部变量例:分析执行结结果f(inta){intb=0;staticintc=3;b++;c++;printf("%5d%5d%5d\n",a,b,c);return(a+b+c);}main(){inta=2,k;for(k=0;k<3;k++)printf("%5d\n",f(a));}6静态变量只只初始化一一次结果:214(a,b,c)7(f(a))21582169(3)register(寄存器)型将使用频率率高的变量量定义为register型,可以提高运运行速度。。寄存器变量量只限于整型、字符型、指针型的局部变量量。寄存器变量量是动态变变量,而且且数目有限限,一般仅允许许说明两个个寄存器变变量,过多多的寄存器器变量的编编译器可能能把它看成成Auto类型。例如:registerintd;registercharc;全局变量---外部变量定义:在函函数外定义义,可为本本文件所有有函数共用用有效范围::从定义变变量的位置置开始到本本源文件结结束,及有有extern说明的其它它源文件外部变量说说明:外部变量定定义与外部部变量说明明不同若外部变量量与局部变变量同名,,则外部变变量被屏蔽蔽外部变量可可用存储类类型:缺省或或static#include<stdio.h>externinta,b;voidswap(){intt;t=a;a=b;b=t;printf(“swap:a=%d,b=%d\n””,a,b);}inta,b;main(){printf(“Entera,b:”);scanf(“%d,%d”,&a,&b);swap();printf(“main:a=%d,b=%d”,a,b);}7Entera,b:5,3↙swap:a=3,b=5main:a=3,b=5运行结果全局变量有有两个问题题:其一:当全局变量量定义在后后,引用它它的函数在在前时,如如何使用该该全局变量量?这就需需要把该全全局变量的的作用域延延伸至该函函数;其二:能否使在某某文件中定定义的全局局变量,在在其它文件件中无须再再次定义而而直接使用用它呢?这这就需要把把全局变量量的作用域域进行延伸伸。C语言可通过过外部变量量说明达到到此目的。。定义说明次数:只只能1次可可说说明多次位置:所所有有函数之外外函函数内或或函数外分配内存::分配内存存,可初始化不不分分配内存,不可初始化化外部变量说说明:extern数据类型变变量表;外部变量定定义与外部部变量说明明不同若外部变量量与局部变变量同名,,则外部变变量被屏蔽蔽例外部变量定义与说明运行结果::max=13#include<stdio.h>externinta,b;//外部变量说说明intmax(intx,inty);//函数说明main(){printf("max=%d",max(a,b));}inta=13,b=-8;//外部变量定定义intmax(intx,inty)//函数定义{intz;z=x>y?x:y;return(z);}#include<stdio.h>inta=7,b=9;//a,b为全局变量量voidf1(intx){intt1;t1=b*x;printf("f1:t1=%d,a=%d,b=%d\n",t1,3*a,3*b);}main(){f1(2);//调用函数f1()printf("main:a=%d,b=%d\n",a,b);}t8#include<stdio.h>inta,b;/*a,b为全局变量量*/voidf1(intx){intt1,a;//重新定义a,没重新定义义b,a值传不过去。。a=x*4;t1=b*3;b=10;printf("f1:t1=%d,a=%d,b=%d\n",t1,a,b);}main(){a=2;b=4;/*此a,b是全局变量,赋值*/f1(2);/*调用函数f1()*/printf("main:a=%d,b=%d",a,b);}9f1:t1=12,a=8,b=10main:a=2,b=10结论:全局变量与与局部变量量同名时,局部变量起作用,全全局变量被被屏蔽(不不影响)变量存储类类型小结静态动态存储方式程序整个运行期间函数调用开始至结束生存期编译时赋初值,只赋一次每次函数调用时赋初值自动赋初值0或空字符不确定未赋初值静态存储区动态区存储区寄存器局部变量外部变量作用域定义变量的函数或复合语句内本文件其它文件局部变量默默认为auto型register型变量个数数受限,且且不能为long,double,float型局部static变量具有全全局寿命和和局部可见见性局部static变量具有可可继承性extern不是变量定定义,可扩展外部部变量作用域域register局部staticauto外部static外部存储类别6.7内部函数、、外部函数数C语言根据函数数能否被其其它源文件件中的函数数调用,将将函数分为为内部函数数和外部函函数。6.7.1内部函数((又称静态态函数)如果一个函函数,只能能被本文件件中的函数数调用,而而不能被同同一程序其其它文件中中的函数调调用,则称称为内部函函数。定义一个内内部函数,,只需在函函数类型前前再加一个个“static”关键字即可可,定义格格式如下::static函数类型函函数名(函数参数表表){……}如staticintfun(a,b,c){……}6.7.1外部函数在定义函数数时,如果果没有加关关键字“static”,或者冠以以“extern”,则表示示此函数是是外部函数数,其定义义格式为::[extern]函数类型函函数名(函数参数表表){……}调用外部函函数时,必必须对被调调用的外部部函数进行行说明。例/*FILE1*/#include<stdio.h>inti;/*在FILE1中定义外部部变量i*/voidfunc();/*外部函数说说明*/main(){ i=5;printf("file1:%d\n",i);func();}/*FILE2*/externinti;/*外部变量说说明,FILE2引用FILE1中定义的外外部变量i*/voidfunc(){ printf("file2:%d\n",i);}该程序的运运行结果是是:file1:5file2:56.8编译预处理理“编译预处理理”是C语言编译系系统的一一个组成部部分。是在在编译前由由编译系统统中的预处处理程序对对源程序的的预处理命命令进行加加工。源程序序中的的预处处理命命令均均以““#”开头,,结束束不加加分号号,以以区别别源程程序中中的语语句,,它们们可以以写在在程序序中的的任何何位置置,作作用域域是自自出现现点到到源程程序的的末尾尾。预处理理命令令包括括执行行宏定定义(宏替换换)、包含含文件件和条条件编编译。。一.宏定义义简单宏宏定义义1.一般形形式为为:#define宏名串串(宏体)如:#definePI3.14159/*定义后后,可以用用PI来代替替串3.14159*/2.宏定义义的作作用在宏定定义之之后,该程序序中宏宏名就就代表表了该该字符符串。。说明:占单独独书写写行语句尾尾不加加分号号3.说明①可以以用#undef命令终终止宏宏定义义的作作用域域。例例如::#undefPI②宏定义义的嵌嵌套使使用#defineR3.0#definePI3.1415926#defineL2*PI*R/*宏体是是表达达式*/#defineSPI*R*Rmain(){printf("L=%f\nS=%f\n",2*PI*R,PI*R*R);/*2*PI*R替换L,PI*R*R替换S*/}t6-1程序运运行结结果如如下::L=18.849556S=28.274333③双引号号内与与宏同同名的的字母母不作作宏展展开.main(){printf("L=%f\nS=%f\n",L,S);}t6-1#defineX5#defineYX+1#defineZY*X/2main(){inta=Y;printf("%d\n",Z);printf("%d\n",--a);}t6-2//Z=Y*X/2=5+1*5/2=7运行结结果::75带参数数的宏宏定义义1.带参数数的宏宏定义义的一一般形形式为为#define宏名(参数表表)字字符串串#defineS(a,b)((a)*(b))2.带实参参的宏宏名被被展开开宏名被被所定定义的的宏体体替换换,宏体中中的形形参按按从左左到右右的顺序被实参参替换换。例如:area=S(3,2);展开为为:area=((3)*(2));宏体及及各形形参外外一般般应加加括号号())一般写写成::#definePOWER(x)((x)*(x))x=4;y=6;z=POWER(x+y);宏展开开:z=((x+y)*(x+y));例#definePOWER(x)x*xx=4;y=6;z=POWER(x+y);宏展开开:z=x+y*x+y;结果为为:100结果为为:34课堂练练习::#include<stdio.h>#defineMIN(x,y)(x)<(y)?(x):(y)main(){inti,j,k;i=10;j=15;k=10*MIN(i,j);printf("%d\n",k);}A)15B)100C)10D)150//10*i<j?10*10<15?(10):(15)使用宏宏替换换应注注意的的问题题(1)宏名与与宏体体之间间用空空格相相隔,,宏名名和参参数之之间不不能有有空格格;如有宏宏定义义:#definef(x)((x)––1)/*宏名f(x)中有空空格*/(2)宏名尽尽管是是字符符串,但不能能用引引号括括起来来(3)在宏定定义中中结尾尾不能能有分分号””;””(4)宏定义中的的参数尽量量用圆括号号括起来以以免错误.(5)较长的宏定定义在一行行中写不下下时,要在在本行结尾尾使用反斜斜杠表示续续行。如:#defineOUTPUTprintf(“Thisisaninteresting\programwhichteachespepolehowtousedefine\command”)t6-3这是比较特特殊的,因为在C
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度文化产业合同协议存款创意产业合作协议
- 2025年度股权质押贷款担保合同范本-@-1
- 二零二四年外债转贷业务借款合同标准3篇
- 2025年度知识产权合法委托代理合同实施细则
- 2025年度户外灯箱广告牌多媒体内容制作合同
- 二零二五年度品牌合作推广服务合同模板4篇
- 2025年度装载机二手市场交易合同范本
- 2025年度海运货物代理货物清关代理合同范本
- 2025年高端锅具出口贸易代理合同范本
- 2025年度高温高压储油罐定制加工合同4篇
- 2024年湖南高速铁路职业技术学院高职单招数学历年参考题库含答案解析
- 上海铁路局招聘笔试冲刺题2025
- 国旗班指挥刀训练动作要领
- 春季安全开学第一课
- 植物芳香油的提取 植物有效成分的提取教学课件
- 肖像绘画市场发展现状调查及供需格局分析预测报告
- 2021-2022学年辽宁省重点高中协作校高一上学期期末语文试题
- 同等学力英语申硕考试词汇(第六版大纲)电子版
- 墓地个人协议合同模板
- 2024年部编版初中语文各年级教师用书七年级(上册)
- (11.3.1)-10.3蒸汽压缩制冷循环
评论
0/150
提交评论