计算机本科C语言讲稿-编译预处理课件.ppt

上传人(卖家):三亚风情 文档编号:3391931 上传时间:2022-08-26 格式:PPT 页数:60 大小:199.01KB
下载 相关 举报
计算机本科C语言讲稿-编译预处理课件.ppt_第1页
第1页 / 共60页
计算机本科C语言讲稿-编译预处理课件.ppt_第2页
第2页 / 共60页
计算机本科C语言讲稿-编译预处理课件.ppt_第3页
第3页 / 共60页
计算机本科C语言讲稿-编译预处理课件.ppt_第4页
第4页 / 共60页
计算机本科C语言讲稿-编译预处理课件.ppt_第5页
第5页 / 共60页
点击查看更多>>
资源描述

1、第六章第六章 预处理命令预处理命令宏定义宏定义文件包含文件包含条件编译条件编译6.1 概述概述 1.所谓预处理是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。语言提供了多种预处理功能,如宏定义、文件包含、条件编译等。合理地使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。2 可执行程序形成的三个过程 预处理、编译和连接是形成可执行程序的三个 重要过程,这三个过程的每一步都可将一种形 式的程序代码改变成另一种形式的程序代

2、码。1)预处理程序负责处理组成程序的预处理命 令,从而将带有预处理命令的程序文件转 化为纯粹的C程序。c:turboc2zxjc1.cvoid p1()printf(“*n”);c:turboc2zxjc2.cvoid p2()printf(“my name is zxjn”);c:turboc2zxjc3.c#include“c1.c”#include“c2.c”main()p1();p2();p1();经过预处理程序(经过预处理程序(预编译程序预编译程序)的处理,从而将)的处理,从而将带有预处理命令的程序文件带有预处理命令的程序文件c3.c转化为:转化为:void p1()void p1(

3、)printfprintf(“(“*n”);n”);void p2()void p2()printfprintf(“my name is zxjn”);(“my name is zxjn”);main()main()p1();p1();p2();p2();p1();p1();2)2)编译程序:编译程序:将一个个将一个个C C源程序翻译成对应的二进源程序翻译成对应的二进 制代码文件制代码文件(后缀名为后缀名为.obj.obj的文件的文件)。3)3)连接程序:连接程序:将组成程序的所有将组成程序的所有.obj.obj和用到的库和用到的库 文件连接起来,形成一个完整的可执行程序。文件连接起来,形成一

4、个完整的可执行程序。6.2宏定义宏定义 在语言源程序中允许用一个标识符来表示一个字符串,称为“宏”。被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。在语言中,“宏”分为有参数和无参数两种。6.2.1无参宏定义无参宏定义其定义的一般形式为:#define 标识符 字符串其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。例如:

5、#define N 100#define M(y*y+3*y)#define PR printf【例【例6.16.1】#define M#define M(y(y*y+3y+3*y)y)main()main()int s,y;int s,y;printf(input a number:);printf(input a number:);scanf(%d,&y);scanf(%d,&y);s=3 s=3*M+4M+4*M+5M+5*M;M;printf printf(s=%dn,s);(s=%dn,s);宏定义宏调用经过预处理程序处理(宏展开)之后纯粹的经过预处理程序处理(宏展开)之后纯粹的C

6、C代码代码 main()main()int s,y;int s,y;printf(input a number:);printf(input a number:);scanf scanf(%d,&y);(%d,&y);s=3 s=3*(y(y*y+3y+3*y)y)+4+4*(y(y*y+3y+3*y)y)+5+5*(y(y*y+3y+3*y)y);printf printf(s=%dn,s);(s=%dn,s);对于宏定义还要说明以下几点:1)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源

7、程序时发现。2)宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。3)宏定义其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。例如:例如:#define PI 3.14159#define PI 3.14159 main()main()f1()f1()例如:例如:#define PI 3.14159#define PI 3.14159 main()main()#undef#undef PI PI f1()f1()4)宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。【例9.2】#define OK 100main()printf(OK);p

8、rintf(n);5)5)宏定义允许嵌套,宏定义允许嵌套,在宏定义的字符串中可以在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程使用已经定义的宏名。在宏展开时由预处理程序层层代换。序层层代换。例如:例如:#define PI 3.1415926#define PI 3.1415926#define S PI#define S PI*y y*y y /*PI PI是已定义的宏名是已定义的宏名*/对语句:对语句:printfprintf(%f,S);(%f,S);在宏代换后变为:在宏代换后变为:printf(%f,3.1415926printf(%f,3.1415926*y y*y)

9、;y);6)6)习惯上宏名用大写字母表示,习惯上宏名用大写字母表示,以便于与变量以便于与变量区别区别;但也允许用小写字母。但也允许用小写字母。7)7)对对“输出格式输出格式”作宏定义,可以减少书写麻烦。作宏定义,可以减少书写麻烦。【例【例6.36.3】中就采用了这种方法。】中就采用了这种方法。#define P printf#define P printf#define D%dn#define D%dn#define F%fn#define F%fnmain()main()int int a=5,c=8,e=11;a=5,c=8,e=11;float b=3.8,d=9.7,f=21.08;f

10、loat b=3.8,d=9.7,f=21.08;P(D F,a,b);P(D F,a,b);P(D F,c,d);P(D F,c,d);P(D F,e,f);P(D F,e,f);6.2.2带参宏定义带参宏定义 语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。带参宏定义的一般形式为:#define 宏名(形参表)字符串带参宏调用的一般形式为:宏名(实参表);例如:例如:#define#define M(y)M(y)y y*y+3y+3*y /y /*宏定义宏定义*/k=k=M(5)M(5);/;/*

11、宏调用宏调用*/经预处理程序的预编译,在宏展开时,用实参经预处理程序的预编译,在宏展开时,用实参5 5去代替形参去代替形参y y,宏展开后的语句为:,宏展开后的语句为:k=5k=5*5+35+3*5 5【例6.4】#define MAX(a,b)(ab)?a:bmain()int x,y,max;printf(input two numbers:);scanf(%d%d,&x,&y);max=MAX(x,y);printf(max=%dn,max);经预编译后:main()int x,y,max;printf(input two numbers:);scanf(%d%d,&x,&y);max=

12、(xy)?x:y;printf(max=%dn,max);对于带参的宏定义有以下问题需要说明:1.带参宏定义中,宏名和形参表之间不能有空格出现。例如把:#define MAX(a,b)(ab)?a:b写为:#define MAX (a,b)(ab)?a:b2.带参宏定义与函数区别:1)在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。函数的形参有类型,当它所在函数调用时得到存储空间。2)宏展开时实参对形参只是简单的代换,而函数调用时实参值要传给形参,进行“值传递”。3.在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。【例9.5】#define SQ(y)(y)*(y)main

13、()int a,sq;printf(input a number:);scanf(%d,&a);sq=SQ(a+1);printf(sq=%dn,sq);4.在宏定义中,字符串内的形参通常要用括号括起来以避免出错。【例9.6】#define SQ(y)y*ymain()int a,sq;printf(input a number:);scanf(%d,&a);sq=SQ(a+1);printf(sq=%dn,sq);运行结果为:input a number:3sq=7【例6.8】#define SQ(y)(y)*(y)main()int a,sq;printf(input a number:)

14、;scanf(%d,&a);sq=160/SQ(a+1);printf(sq=%dn,sq);对于宏定义不仅应在参数两侧加括号,也应在整个字符串外加括号。5.宏定义也可用来定义多个语句,在宏展开时,把这些语句又代换到源程序内。看下面的例子。【例【例9.119.11】#define V(s1,s2,s3,v)s1=l#define V(s1,s2,s3,v)s1=l*w;s2=lw;s2=l*h;s3=wh;s3=w*h;v=wh;v=w*l l*h hmain()main()int int l=3,w=4,h=5,sa,sb,sc,vv;l=3,w=4,h=5,sa,sb,sc,vv;V(sa

15、,sb V(sa,sb,sc,vv);,sc,vv);printf(sa=%dnsb=%dnsc=%dnvv printf(sa=%dnsb=%dnsc=%dnvv=%dn,=%dn,sa,sb sa,sb,sc,vv);,sc,vv);6.3文件包含文件包含 文件包含是C预处理程序的另一个重要功能。#include命令告诉预处理程序,将其后面所跟的文件的内容插入到当前文件中。即把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。#include命令行的两种形式为:#include#include 文件名 例如:#include stdio.h#incl

16、ude math.h 在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量,从而节省时间,并减少出错。对文件包含命令还要说明以下几点:1.包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如以下写法都是允许的:#include stdio.h#include 但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的),而不在源文件目录去查找;使用双引号则表示首先在当前的源

17、文件目录中查找,若未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。2.一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。3.文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。#include void p().File1.c#include void s().File2.c#include void main().File3.c 6.4条件编译条件编译 预处理程序提供了条件编译的功能。可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。这对于程序的移植和调试是很有用的。条件编译有三种形式

18、,下面分别介绍:1.第一种形式:#ifdef 标识符 程序段1#else 程序段2#endif#ifdef 标识符 程序段#endif2.第二种形式:#ifndef 标识符 程序段1#else 程序段2#endif 与第一种形式的区别是将“ifdef”改为“ifndef”。它的功能是,如果标识符未被#define命令定义过则对程序段1进行编译,否则对程序段2进行编译。这与第一种形式的功能正相反。3.第三种形式:#if 常量表达式 程序段1#else 程序段2#endif它的功能是,如常量表达式的值为真(非0),则对程序段1 进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下,完成不同

19、的功能。【例6.12】#define R 1main()float c,r,s;printf(input a number:);scanf(%f,&c);#if R r=3.14159*c*c;printf(area of round is:%fn,r);#else s=c*c;printf(area of square is:%fn,s);#endif本例中采用了第三种形式的条件编译。在程序第一行宏定义中,定义R为1,因此在条件编译时,常量表达式的值为真,故计算并输出圆面积。上面介绍的条件编译当然也可以用条件语句来实现。但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条

20、件编译,则根据条件只编译其中的程序段1或程序段2,生成的目标程序较短。如果条件选择的程序段很长,采用条件编译的方法是十分必要的。6.5本章小结本章小结1.预处理功能是语言特有的功能,它是在对源程序正式编译前由预处理程序完成的。程序员在程序中用预处理命令来调用这些功能。2.宏定义是用一个标识符来表示一个字符串,这个字符串可以是常量、变量或表达式。在宏展开时用该字符串代换宏名。3.宏定义可以带有参数,宏展开时是以实参代换形参。而不是“值传送”。4.为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。5.文件包含是预处理的一个重要功能,它可用来把多个源文件连接成

21、一个源文件进行编译,结果将生成一个目标文件。6.条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。7.使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计。再见!本章练习一、选择题以下叙述不正确的是_A)预处理命令行都必须以#号开始B)在程序中凡是以#号开始的语句行都是预处理命令行C)C程序在执行过程中对预处理命令行进行处理D)以下是正确的宏定义E)#define IBM_PC2.以下叙述中正确的是_A)在程序的一行上可以出现多个预处理命令行B)使用带参的宏时,参数的类型应与宏定义时的一致C)宏替换不占用运行时间,只占

22、编译时间D)在以下定义中C R是称为“宏名”的标识符E)#define C R 0453.请读程序:#define ADD(x)x+xmain()int m=1,n=2,k=3;int sum=ADD(m+n)*k;printf(“sum=%d”,sum);上面程序的运行结果是_A)sum=9 B)sum=10C)sum=12D)sum=184.以下程序的运行结果是_#define MIN(x,y)(x)(y)?(x):(y)main()int i=10,j=15,k;k=10*MIN(i,j);printf(“%dn”,k);A)10B)15C)100D)1505.在宏定义#define P

23、I 3.14159中,用宏名PI代替一个_A)常量B)单精度数C)双精度数D)字符串E)6.以下有关宏替换的叙述不正确的是_F)宏替换不占用运行时间G)宏名无类型H)宏替换只是字符替换I)宏名必须用大写字母表示7.以下程序的运行结果是_#include“stdio.h”#define FUDGE(y)2.84+y#define PR(a)printf(“%d”,(int)(a)#define PRINT1(a)PR(a);putchar(n)/*宏定义可以嵌套*/main()int x=2;PRINT1(FUDGE(5)*x);A)11 B)12 C)13 D)158.C语言的编译系统对宏命令

24、的处理是_A)在程序运行时进行的B)在程序连接时进行的C)和C程序中的其它语句同时进行编译的D)在对源程序中其它成份正式编译之前进行的9.若有宏定义如下:#define X 5#define Y X+1#define Z Y*X/2则执行以下printf语句后,输出结果是_int a;a=Y;printf(“%dn”,Z);printf(“%dn”,-a);A)7 B)12 C)12 D)7B)6 6 5 510.若有以下宏定义:#define N 2#define Y(n)(N+1)*n)则执行语句z=2*(N+Y(5);后的结果是_A)语句有错误B)z=34C)z=70D)z无定值11.若

25、有宏定义:#define MOD(x,y)x%y 则执行以下语句后的输出为_ int z,a=15,b=100;z=MOD(b,a);printf(“%dn”,z+);A)11B)10C)6D)宏定义不合法12.#include#define MUL(x,y)(x)*y main()int a=3,b=4,c;c=MUL(a+,b+);printf(“%dn”,c);上面程序的输出结果是_A)12B)15C)20D)16#define LETTER 0main()char str20=“C language”,c;int i;i=0;while(c=stri)!=0)i+;#if LETTER

26、 if(c=A&c=a&c=z)c-=32;#endif printf(“%c”,c);13.程序的运行程序的运行结果是:结果是:A)ClanguageB)clanguageC)CLANGUGED)cLANGUGE二、填空题1 C语言提供了三种预处理语句,它们是_、_和条件编译。2下面程序中for循环的执行次数是_8_.3#include 4#define N 25#define M N+16#define NUM(M+1)*M/27void main()8int t;9 for(t=1;t=NUM;t+)10 ;11 3下面程序的输出是_4#define PR(ar)printf(“%d”,

27、ar)5main()6int j,a=1,3,5,7,9,11,13,15,*p=a+5;7 for(j=3;j;j-)8 switch(j)9 case 1:10 case 2:PR(*p+);break;11 case 3:PR(*(-p);12 13 4 分析下面的程序,给出结果var.h文件int M1,M2;/*通过全局变量可以在主调函数和被调用函数之间可以数据传递*/int a55;disp.c文件的内容如下所示:#include#include var.hmain()void solve();int i,j;for(i=0;i5;i+)for(j=0;j5;j+)scanf(“%

28、d”,&aij);solve();printf(“M1=%d,M2=%d”,M1,M2);voidsolve()inti,j;M1=a00;M2=a00;for(i=0;i5;i+)for(j=0;j5;j+)if(M1aij)M2=aij;课后习题9.1定义一个带参数的宏,使两个参数的值互换,并写出定义一个带参数的宏,使两个参数的值互换,并写出程序,输入两个数作为使用宏时的实参,输出已交换程序,输入两个数作为使用宏时的实参,输出已交换后的值。后的值。#defineM(x,y)t=x;x=y;y=t#includevoidmain()inta,b,t;printf(请输入两个整数给请输入两个整

29、数给a和和bn);scanf(%d%d,&a,&b);printf(输入输入a和和b的值为:的值为:%4d%4dn,a,b);M(a,b);printf(交换后交换后a和和b的值为:的值为:%4d%4dn,a,b);9.2输入两个整数,求它们相除的余数,用带参输入两个整数,求它们相除的余数,用带参的宏来实现,编程序。的宏来实现,编程序。#defineM(x,y)x%y#includevoidmain()inta,b;printf(请输入两个整数给请输入两个整数给a和和bn);scanf(%d%d,&a,&b);printf(“a和和b相除的余数为:相除的余数为:%4dn,M(a,b);9.3三

30、角形的面积为三角形的面积为area=sqrt(s*(s-a)*(s-b)*(s-c);其中其中s为周长;为周长;定义两个带参的宏,一个用来求定义两个带参的宏,一个用来求s,另一个宏用来求,另一个宏用来求area,写程,写程序,在程序中用带实参的宏名来求面积。序,在程序中用带实参的宏名来求面积。#include#include#defineS(x,y,z)(1.0/2*(x+y+z)#defineAREA(x,y,z)sqrt(S(x,y,z)*(S(x,y,z)-x)*(S(x,y,z)-y)*(S(x,y,z)-z)voidmain()inta,b,c;printf(“请输入三个整数给请输入

31、三个整数给a、b和和c:n”);scanf(%d%d%d,&a,&b,&c);printf(“面积为:面积为:%fn,AREA(a,b,c);9.4给年份给年份year定义一个宏,以判别该年份是否为闰年定义一个宏,以判别该年份是否为闰年#include#defineS(y)(y%4=0&y%100!=0)|(year%400=0)voidmain()intyear;printf(“请输入一个年份请输入一个年份:n”);scanf(%d,&year);if(S(year)printf(“%d是闰年是闰年n”,year);elseprintf(“%d不是闰年不是闰年n”,year);9.6请设计输

32、出实数的格式,包括:请设计输出实数的格式,包括:1)一行输出一行输出1个实数,个实数,2)一行一行输出输出2个实数,个实数,3)一行输出一行输出3个实数。实数用个实数。实数用%6.2f格式输出。格式输出。#include#definePRprintf#defineN“n”#defineD“%6.2f”#defineD1DN#defineD2DDN#defineD3DDDNvoidmain()floata,b,c;printf(“请输入请输入a,b,c的值的值:n”);scanf(“%f%f%f”,&a,&b,&c);PR(D1,a);PR(D2,a,b);PR(D3,a,b,c);9.8分别用

33、函数和带参的宏,从分别用函数和带参的宏,从3个数中找出最大数。个数中找出最大数。/*用带参的宏来实现用带参的宏来实现*/#include#defineMAX(x,y,z)if(xy)max=x;elsemax=y;if(maxy)max=x;elsemax=y;if(max=z)max=z;returnmax;voidmain()inta,b,c;printf(“请输入请输入a,b,c的值的值:n”);scanf(“%d%d%d”,&a,&b&c);printf(“a,b,c的最大值为的最大值为:%dn”,max(a,b,c);9.10用条件编译方法实现以下功能:用条件编译方法实现以下功能:输

34、入一行电报文字,可以任选两种输出:一为原输入一行电报文字,可以任选两种输出:一为原文输出;二为将字母变成其下一字母。用文输出;二为将字母变成其下一字母。用#define命令来控制是否要译成密码,例如:命令来控制是否要译成密码,例如:#defineCHANGE1则输出密码,若则输出密码,若#defineCHANGE0,按原码输出。,按原码输出。#defineCHANGE1#defineN100#includevoidmain()charsN,t;printf(请输入一行字母请输入一行字母n);scanf(%s,s);#ifdefCHANGEfor(t=0;st!=0;t+)st+;if(st=Z&st=z)st-=26;puts(s);#elseputs(s);#endif

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(计算机本科C语言讲稿-编译预处理课件.ppt)为本站会员(三亚风情)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|