已阅读5页,还剩35页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第8章编译预处理,第8章编译预处理,8.1结构体类型的概述8.2宏定义8.3文件包含8.4条件编译,8.1编译预处理命令,1.编译预处理2.编译预处理命令,1.编译预处理,预处理由专门的预处理程序负责完成。当对一个源文件进行编译前,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。中间不需要人为干预。编译预处理是由编译系统中的预处理命令进行的语言提供了多种预处理功能,如文件包含、宏定义、条件编译等。,2.编译预处理命令,编译预处理命令主要有三种,即:宏定义、文件包含、条件编译。所有的编译预处理命令均以#符号开头,各占用一个单独的书写行,末尾不用分号作结束符。编译预处理命令可以出现在程序的任何位置,其作用域是自出现的地方开始直到源程序的末尾。,8.2宏定义,8.2.1无参宏的定义8.2.2带参数宏的定义8.2.3宏替换与函数调用的区别8.2.4宏定义的解除和重新定义宏,8.2.1无参宏的定义,所谓无参宏就是宏名后不带任何参数。其定义的一般形式为:#define宏名字符串(或数值)其中的“#”表示这是一条预处理命令,C语言中凡是以“#”开头的命令都为预处理命令。“define”为宏定义命令。宏定义在使用中应注意以下几点:(1)宏名的前后应有空格。(2)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名。(3)宏定义命令其后不要跟分号。,(4)字符串(或数值)中如果出现运算符号,则要注意替换后的结果,通常可以在合适的位置加上括号。例8.1宏应用举例。#defineN(8*x+x*x)/*定义N来替代表达式(8*x+x*x)*/main()ints,x;printf(pleaseinputanumber:);scanf(%d,程序的运行情况为:pleaseinputanumber:4s=864,分析:上例程序中首先进行宏定义,定义N来替代表达式(8*x+x*x),在s=5*N+6*N+7*N中对N进行了宏调用。经宏展开后该语句变为下面的形式:s=5*(8*x+x*x)+6*(8*x+x*x)+7*(8*x+x*x);如果在宏定义中表达式(8*x+x*x)两边的括号没有了,预处理时将会变成:s=5*8*x+x*x+6*8*x+x*x+7*8*x+x*x;显然发生了错误,因此加括号和不加括号的意思和答案完全不一样。所以在进行宏定义时必须十分注意。应保证在宏代换之后不发生错误。,(5)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。例如图8-1所示:,图8-1种的PI只在main函数中有效,在函数hans中是无效的。,(6)C语言规定,宏名如果出现在字符串常量中或者用双引号括起来的字符串内时,将不作为宏名处理,不对其进行宏替换。例如:#definePI3.14159floatr=1.0;printf(”s=PI*r*r=%fn”,PI*r*r);则程序运行时,输出结果是:s=PI*r*r=3.14159*1.0*1.0=3.141590而不是:s=3.14159*r*r=3.14159*1.0*1.0=3.141590,例8.2宏名出现在双引号内部时的应用举例。#defineOK800/*定义OK来替代表达式800*/main()printf(OK);/*宏名位于双引号内进行输出*/printf(n);程序的运行结果是:OK而不是800,因为双引号中的宏名不不作宏名处理,没有进行宏替换。,(7)宏定义允许嵌套,在宏定义的字符串(或数值)中可以使用已经定义的宏名。在宏展开时由预处理程序层层代换。例如:#definePI3.14159#defineSPI*r*r/*其中的PI是已定义的宏名*/printf(%f,S);在宏代换后变为:printf(%f,3.14159*r*r);(8)习惯上宏名用大写字母表示,以便与变量区别。但也可以用小写字母,用大写字母不是规定,只是一种习惯。建议用大写字母表示宏名。(9)对“输出格式”作宏定义,可以减少书写麻烦。,例8.3对输出格式作宏定义应用举例。#definePprintf/*定义P来替代printf*/#defineD%dn/*定义D来替代%dn*/#defineF%fn/*定义F来替代%fn*/main()inta=7,c=32,e=20;floatb=20.1,d=8.7,f=56.08;P(DF,a,b);/*进行宏调用*/P(DF,c,d);P(DF,e,f);,该程序的运行结果为:720.100000328.7000002056.080002,例8.4编程实现:从输入的10000个整数中寻找并输出最大数和最小数。分析:如果直接编一个这样的程序,每次调试程序时,都要连续输入10000个整数,调试工作量很大。为了解决这个问题,可以使用宏定义将整数的个数定义小一点,比如定义为5,先调试程序,程序正确后,再将宏定义中的个数改为10000。#defineM5/*定义M替代5*/main()intfM,max,min;inti;printf(PleaseenterMnumber:n);for(i=0;i/*定义LAG替代*/#defineSMAmain()inti=32;intj=60;if(iLAGj)printf(n%dlargerthan%dn,i,j);elseif(iEQj)printf(n%dequalto%dn,i,j);elseif(iSMAj)printf(n%dsmallerthan%dn,i,j);elseprintf(nNosuchvalue.n);,程序的运行结果为:32smallerthan60,8.2.2带参数宏的定义,宏定义还有一个特点,就是宏替换名可以带有形式参数。在程序中,可以用实际参数代替这些形式参数。例8.6带参数宏应用举例一。#include#defineMAX(a,b)(ab)?a:b/*定义M(a,b)替代表达式(ab)?a:b*/main()inti=18,j=16;printf(Themaxnumberis:%d,MAX(i,j);,程序的运行结果为:Themaxnumberis:18,使用带参的宏定义时需要注意以下几点:(1)带参宏定义中,宏名和形参表之间不能有空格出现。例如下面的宏:#defineMIN(a,b)(ab)?a:b如果写成如下的形式:#defineMIN(a,b)(ab)?a:b/*代表空格*/则C语言将认为该宏没有参数,宏名MIN代表字符串“(a,b)(ab)?a:b”这显然是错误的。(2)在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。,例8.7带参数宏应用举例二。#defineB(x)(x)*(x)*(x)/*定义B(x)替代表达式(x)*(x)*(x),x为形参*/main()inta,b;printf(pleaseinputanumber:);scanf(%d,程序的运行结果为:pleaseinputanumber:12b=8000,分析:该程序中的宏在展开时,用a+8代换x,再用(x)*(x)*(x)代换B(x),得到如下语句:b=(a+8)*(a+8)*(a+8);,8.2.3宏替换与函数调用的区别,宏替换和函数调用的区别是:函数在调用的时候,要把实参表达式的值求出来再赋予形参。而宏代换中对实参表达式不作计算直接照原样代换。同时,同一表达式用函数处理与用宏处理两者的结果有可能不同。例8.8宏替换与函数调用区别举例。,程序一:#includemain()inti=1;while(i=8)printf(%dn,B(i+);B(intx)/*名为B的函数*/return(x)*(x)*(x);,程序的运行结果如下:182764125216343512,程序二:#include#defineB(x)(x)*(x)*(x)/*定义一个名为B的宏*/main()inti=1;while(i=8)printf(%dn,B(i+);,该程序的运行结果如下:6120504,8.2.4宏定义的解除和重新定义宏,解除宏定义的一般形式为:#undef宏名其中,宏名是在此之前已定义过的。#undef的功能是解除前面已经定义的宏,使之不再起作用。例如:#definePDP1#defineMUL(x)(x)*(x).#undefPDP#undefMUL使宏PDP和MUL(x)只在#undef之前的程序中有效,在#undef之后就不能再使用这两个宏。,#undef的另一个作用是重新进行宏定义。C语言规定:符号常量和带参数的宏都不能重复定义,即程序中不能定义同名的宏。例如,在程序的开头定义了SIZE是256,到程序的另一个地方需要定义SIZE是512,使用#defineSIZE256.#defineSIZE512是不允许的。但是,如果在定义SIZE为512之前,用#undefSIZE来解除原先的定义,就可以定义SIZE为512。,8.3文件包含,8.3.1文件包含的格式8.3.2文件包含的功能,8.3.1文件包含的格式,文件包含命令的一般形式为:#include文件名文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。例如:#includestdio.h文件包含命令还可以有以下的形式:#include例如:#include,说明:文件包含命令两种形式是有区别的:使用尖括号表示在包含文件目录中去查找,而不在源文件目录中查找。其中包含目录是由用户在设置环境时设置的。使用双引号则表示首先在当前的源文件目录中查找,如果未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。对文件包含命令还需要注意以下几点:(1)包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。(2)一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。(3)文件包含命令也允许嵌入到其他文件中。(4)包含文件的内容必须是C语言的源程序清单。,8.3.2文件包含的功能,在编译预处理时,命令行将被包含进来的文件内容替换。例8.9编写程序实现:输入半径,并计算和显示该半径对应的圆周长、圆面积、球表面积和球体积。分析:将计算圆的周长和面积、球的表面面积和体积的计算公式定义为带参数的宏,并将这些宏定义单独存放在文件circle.c中。假设文件circle.c和主程序文件都放在D:TC子目录中。只要在主程序中将circle.c包含进来,就可以直接调用这些宏来计算。,主程序清单为:#includecircle.c“/*主文件中包含文件circle.c*/main()floatr;printf(InputR:);scanf(%f,/*调用函数VOLUME(r)*/,文件circle.c的内容如下:#definePI3.141593/*定义PI代替3.141593*/#defineCIRCLE(r)2*PI*(r)/*定义CIRCLE(r)代替2*PI*(r)*/#defineAREA(r)PI*(r)*(r)/*定义AREA(r)代替PI*(r)*(r)*/#defineSURFICE(r)AREA(r)*4/*定义SURFICE(r)代替AREA(r)*4*/#defineVOLUME(r)SURFICE(r)*(r)/3/*定义VOLUME(r)代替SURFICE(r)*(r)/3*/,程序的运行情况为:InputR:1.0C=6.28A=3.14S=12.57V=4.19InputR:4.0C=25.13A=50.27S=201.16V=268.08,8.4条件编译,8.4.1条件编译命令的形式8.4.2条件编译的功能,8.4.1条件编译命令的形式,1.第一种形式2.第二种形式3.第三种形式,1.第一种形式,#ifdef标识符程序段1;#else程序段2;#endif其中的标识符通常是一个符号常量,利用定义该符号常量时所给的值来确定条件是否成立。含义是:如果标识符被define命令定义过,则编译时只编译程序段1的内容,否则编译程序段2的内容。,命令中的“#else”以及其后的程序段2可以省略。此时形式如下:#ifndef程序段1;#endif含义是:如果标识符被define命令定义过,则编译时只编译程序段1的内容,否则不编译程序段1。例8.10条件编译应用举例一。#include#defineMAX100/*定义MAX代替100*/main()inti=10;floatx=25.8;#ifdefMAX/*如果MAX被define命令定义过则输出i的值*/,printf(%dn,i);#else/*如果MAX没有被define命令定义过输出x的值*/printf(%.1fn,x);#endifprintf(%d,%.1fn,i,x);/*输出i和x的值*/,程序的运行结果是:1010,25.8,2.第二种形式,#ifndef标识符程序段1;#else程序段2;#endif含义是:如果标示符没有被define命令定义过时,则编译阶段编译程序段1,否则编译程序段2。,3.第三种形式,#if表达式程序段1;#else程序段2;#endif含义是当指定的表达式为真时,编译程序段1,否则编译程序段2。,例8.11条件编译应用举例二。#include#defineM888
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 劳动合同签订前的员工福利制度
- 临时客服人员聘用合同样本
- 足球场膜结构施工合同
- 超分子水杨酸换肤治疗
- 2022年大学水利专业大学物理下册期末考试试卷C卷-附解析
- 商业空地租赁合同范本
- 2022年大学电气信息专业大学物理二模拟考试试题A卷-含答案
- 餐厅包间地砖铺设合同
- IT行业销售精英聘用合同
- 通信工程监理聘用合同样本
- 电气工程师生涯人物访谈报告
- 三级配电箱电路图(共2页)
- 第三讲 DPS应用(5、专业试验统计)
- 工具式悬挑防护棚安全专项施工方案
- 初中音乐江苏民歌ppt课件
- 《2021国标暖通图集资料》14K117-3 锥形风帽
- 机动车维修企业安全生产标准化考评方法和考评实施细则(完整版)
- 江西省职业培训补贴范围及标准-江西省职业技能鉴定指导中心
- 七年级生物上册(济南版)知识点归纳
- 应急联防联动协议
- D600变频器说明书
评论
0/150
提交评论