书签 分享 收藏 举报 版权申诉 / 60
上传文档赚钱

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

  • 上传人(卖家):三亚风情
  • 文档编号:3391931
  • 上传时间:2022-08-26
  • 格式:PPT
  • 页数:60
  • 大小:199.01KB
  • 【下载声明】
    1. 本站全部试题类文档,若标题没写含答案,则无答案;标题注明含答案的文档,主观题也可能无答案。请谨慎下单,一旦售出,不予退换。
    2. 本站全部PPT文档均不含视频和音频,PPT中出现的音频或视频标识(或文字)仅表示流程,实际无音频或视频文件。请谨慎下单,一旦售出,不予退换。
    3. 本页资料《计算机本科C语言讲稿-编译预处理课件.ppt》由用户(三亚风情)主动上传,其收益全归该用户。163文库仅提供信息存储空间,仅对该用户上传内容的表现方式做保护处理,对上传内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!
    4. 请根据预览情况,自愿下载本文。本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
    5. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007及以上版本和PDF阅读器,压缩文件请下载最新的WinRAR软件解压。
    配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    计算机 本科 语言 讲稿 编译 预处理 课件
    资源描述:

    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

    展开阅读全文
    提示  163文库所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
    关于本文
    本文标题:计算机本科C语言讲稿-编译预处理课件.ppt
    链接地址:https://www.163wenku.com/p-3391931.html

    Copyright@ 2017-2037 Www.163WenKu.Com  网站版权所有  |  资源地图   
    IPC备案号:蜀ICP备2021032737号  | 川公网安备 51099002000191号


    侵权投诉QQ:3464097650  资料上传QQ:3464097650
       


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

    163文库