版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言程序设计基础太原理工大学计算机学院计算机基础部第1章引言第10章编译预处理编译预处理预处理由专门的预处理程序负责完成。当对一个源文件进行编译前,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。中间不需要人为干预。编译预处理是由编译系统中的预处理命令进行的C语言提供了多种预处理功能,如文件包含、宏定义、条件编译等。编译预处理命令编译预处理命令主要有三种,即:宏定义、文件包含、条件编译。所有的编译预处理命令均以#符号开头,各占用一个单独的书写行,末尾不用分号作结束符。编译预处理命令可以出现在程序的任何位置,其作用域是自出现的地方开始直到源程序的末尾。10.1宏定义命令#define
10.2文件包含命令#include
10.3条件编译
10.4编译预处理程序举例
10.1宏定义命令#define
10.1.1无参宏定义10.1.2有参宏定义10.1.3有参宏与函数的区别10.1.4宏定义的解除和重新定义宏
10.1.1无参宏定义1.所谓无参宏就是宏名后不带任何参数。其定义的格式为:#define宏名字符串(或数值)其中的“#”表示这是一条预处理命令,C语言中凡是以“#”开头的命令都为预处理命令。“define”为宏定义命令。2.宏定义在使用中应注意以下几点:(1)宏名的前后应有空格。(2)宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名。(3)宏定义命令其后不要跟分号。(4)字符串(或数值)中如果出现运算符号,则要注意替换后的结果,通常可以在合适的位置加上括号。【例10.1】#include"stdio.h"#defineN3+4/*定义N来替代表达式3+4*/intmain(){intx,y;x=2*N;/*宏调用*/y=2*(N);/*宏调用*/printf("x=%dy=%d\n",x,y);return0;}程序的运行结果为:x=10y=14
分析:本例中用字符串“3+4”代替N,因此第5行的语句执行时,x的值应该为2*3+4,结果为10,而不是2*7=14;而第6行的语句“y=2*(N);”加了小括号,所以y的值为2*(3+4)=14。因此在进行宏定义时必须十分注意,应保证在宏代换之后不发生错误。(5)宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。例如:#definePI3.1415926main(){…}#undefPIhans(){…}PI只在main函数中有效,在函数hans中是无效的。(6)C语言规定,宏名如果出现在字符串常量中或者用双引号括起来的字符串内时,将不作为宏名处理,不对其进行宏替换。【例10.2】#include"stdio.h"#definePI3.14159/*定义PI来替代3.14159*/intmain(){floatc,radius=2.5;printf("c=2*PI*radius=%f\n",2*PI*radius);/*宏名位于双引号内不进行宏代换*/return0;}程序的运行结果为:c=2*PI*radius=15.707950而不是:c=2*3.14159*radius=15.707950(7)宏定义允许嵌套,在宏定义的字符串(或数值)中可以使用已经定义的宏名。在宏展开时由预处理程序层层代换。例如:#definePI3.14159#defineC2*PI*radius/*其中的PI是已定义的宏名*/printf("%f",C);
在宏代换后变为:printf("%f",2*3.14159*radius);(8)习惯上宏名用大写字母表示,以便与变量区别。但也可以用小写字母,用大写字母不是规定,只是一种习惯。建议用大写字母表示宏名。(9)可用宏定义表示数据类型,使书写方便。(10)对“输出格式”作宏定义,可以减少书写麻烦。【例10.3】分析程序的运行结果。#include"stdio.h"#definePprintf#defineD"%d"#defineF"%f\n"intmain(){inta=5,c=8,e=11;doubleb=3.8,d=9.7,f=21.08;P(DF,a,b);P(DF,c,d);P(DF,e,f);return0;}该程序的运行结果为:53.80000089.7000001121.080000
【例10.4】编程实现:从输入的15000个整数中寻找并输出最大数和最小数。
分析:如果直接编一个这样的程序,每次调试程序时,都要连续输入15000个整数,调试工作量很大。为了解决这个问题,可以使用宏定义将整数的个数定义的小一点,比如定义为8,先调试程序,程序正确后,再将宏定义中的个数改为15000。#include"stdio.h"#defineN4/*定义N替代4*/intmain(){inta[N],max,min;inti
;printf("Pleaseenter%dnumber:\n",N);for(i=0;i<N;i++)scanf("%d",&a[i]);/*输入N个整数*/max=min=a[0];for(i=1;i<N;i++)/*在N个整数中找最大数和最小数*/{if(a[i]>max)max=a[i];if(a[i]<min)min=a[i];}printf("max=%d,min=%d\n",max,min);/*输出N个整数中的最大数和最小数*/return0;}程序的运行情况为:Pleaseenter4number:10-24589↙max=89,min=-24说明当程序调试正确无误后,只要把宏定义命令改为:#defineN15000就可以使用该程序来处理15000个整数了。10.1.2有参宏定义1.宏定义还有一个特点,就是宏替换名可以带有形式参数。在程序中,可以用实际参数代替这些形式参数。有参宏定义格式:#define宏名(形参表)字符串有参宏调用格式为:宏名(实参表)
【例10.5】分析程序的运行结果。#include"stdio.h"#defineMAX(x,y)(x>y)?x:y/*有参宏定义*/intmain(){inta,b,max;printf("Inputtwonumbers:");scanf("%d%d",&a,&b);max=MAX(a,b);/*宏调用*/printf("max=%d\n",max);return0
;}程序的运行情况为:Inputtwonumbers:123-24↙max=1232.使用带参的宏定义时需要注意以下几点:(1)带参宏定义中,宏名和形参表之间不能有空格出现。例如下面的宏:#defineMIN(a,b)(a<b)?a:b如果写成如下的形式:#defineMIN
(a,b)(a<b)?a:b/*
代表空格*/则C语言将认为该宏没有参数,宏名MIN代表字符串“(a,b)(a<b)?a:b”这显然是错误的。(2)在宏定义中的形参是标识符,而宏调用中的实参可以是常量、变量和表达式。(3)在宏定义中,字符串内的形参通常要用括号括起来以避免出错。
【例10-6】分析程序的运行结果。#include"stdio.h"#defineV(x)(x)*(x)*(x) /*有参宏定义*/intmain(){inta,volume;printf("Inputanumber:");scanf("%d",&a);volume=V(a+5); /*宏调用,实参为表达式a+5*/printf("volume=%d\n",volume);return0;}程序运行的结果为:Inputanumber:3↙volume=512分析:该程序中的宏在展开时,用a+5代换x,再用(x)*(x)*(x)代换V(x),得到如下语句:volume=(a+5)*(a+5)*(a+5);【例10-7】分析程序的运行结果。#include"stdio.h"#defineV(x)x*x*x /*有参宏定义*/intmain(){inta,volume;printf("Inputanumber:");scanf("%d",&a);volume=V(a+5); /*宏调用,实参为表达式a+5*/printf("volume=%d\n",volume);return0;}程序的运行情况为:Inputanumber:3↙volume=38分析:该程序中的宏在展开时,用a+5代换x,再用x*x*x代换V(x),得到如下语句:volume=a+5*a+5*a+5;【例10.8】分析程序的运行结果。#include"stdio.h"#defineV(x)(x)*(x)*(x)/*有参宏定义*/intmain(){inta,volume;printf("Inputanumber:");scanf("%d",&a);volume=2560/V(a+5);/*宏调用,实参为表达式a+5*/printf("volume=%d\n",volume);return0;}程序的运行情况为:Inputanumber:3↙volume=20480分析:该程序中的宏在展开时,用a+5代换x,再用(x)*(x)*(x)代换V(x),得到如下语句:volume=2560/(a+5)*(a+5)*(a+5);【例10.9】分析程序的运行结果。#include"stdio.h"#defineV(x)((x)*(x)*(x))/*有参宏定义*/intmain(){inta,volume;printf("Inputanumber:");scanf("%d",&a);volume=2560/V(a+5);/*宏调用,实参为表达式a+5*/printf("volume=%d\n",volume);return0;}程序的运行情况为:Inputanumber:3↙volume=5分析:该程序中的宏在展开时,用a+5代换x,再用((x)*(x)*(x))代换V(x),得到如下语句:volume=2560/((a+5)*(a+5)*(a+5));(4)宏定义也可用来定义多个语句,在宏调用时,把这些语句又代换到源程序内。【例10.10】分析程序的运行结果。#include"stdio.h"#defineSSSV(s1,s2,s3,v)s1=l*w;s2=l*h;s3=w*h;v=w*l*h;/*有参宏定义*/intmain(){intl=3,w=4,h=5,sa,sb,sc,vv;SSSV(sa,sb,sc,vv);/*宏调用*/printf("sa=%dsb=%dsc=%dvv=%d\n",sa,sb,sc,vv);return0;}程序的输出结果:sa=12sb=15sc=20vv=60分析:用宏名SSSV表示4个赋值语句,4个形参分别为4个赋值符左部的变量。在宏调用时,把4个语句展开并用实参代替形参。使计算结果送入实参之中。
10.1.3宏替换与函数的区别宏替换和函数调用的区别是:(1)定义形式上不同(2)处理时间上不同(3)处理方式上不同(4)时空的开销上不同(5)类型的要求上不同
【例10.11】比较下面试图输出整数1~5的平方的两个程序。(1)采用函数的程序#include"stdio.h"intsq(intx);intmain(){inti=1;while(i<=5)printf("%d",sq(i++));return0
;}intsq(intx){return(x*x);}
程序的运行结果如下:1491625
(2)采用有参宏定义的程序#include"stdio.h"#defineSQ(x)((x)*(x))intmain(){inti=1;while(i<=5)printf("%d",SQ(i++));return0;}该程序的运行结果如下:1925分析:当i=1时,先被替换,执行输出语句printf("%d",((1)*(1)));输出1;接着i经过两次自增,变为3,再被替换,输出9;然后i经过两次自增,变为5,再被替换,输出25;又经过两次自增,变为7,不再重复,程序结束。10.1.4宏定义的解除和重新定义宏1.解除宏定义的一般形式为:#undef宏名其中,宏名是在此之前已定义过的。#undef的功能是解除前面已经定义的宏,使之不再起作用。例如:#definePI3.14#defineMUL(x)((x)*(x))…#undefPI#undefMUL使得宏PI和MUL(x)只在#undef之前的程序中有效,在#undef之后就不能再使用这两个宏。2.#undef的另一个作用是重新进行宏定义C语言规定:符号常量和带参数的宏都不能重复定义,即程序中不能定义同名的宏。例如,在程序的开头定义了PI是3.14,到程序的另一个地方需要定义PI是3.1415926,使用#definePI3.14...#definePI3.1415926是不允许的。但是,如果在定义PI为3.1415926之前,用#undefPI来解除原先的定义,就可以定义PI为3.1415926。10.2文件包含命令#include
10.2.1文件包含的格式10.2.2文件包含的功能10.2.1文件包含的格式1.文件包含命令的格式为:#include<文件名>或#include"文件名"文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行,从而把指定的文件和当前的源程序文件连成一个源文件。例如:#include"stdio.h"#include<math.h>
说明:文件包含命令两种形式是有区别的:①使用尖括号表示在包含文件目录中去查找,而不在源文件目录中查找。其中包含目录是由用户在设置环境时设置的。②使用双引号则表示首先在当前的源文件目录中查找,如果未找到才到包含目录中去查找。用户编程时可根据自己文件所在的目录来选择某一种命令形式。2.对文件包含命令的几点说明:(1)包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。(2)一个include命令只能指定一个被包含文件,若有多个文件要包含,则需用多个include命令。(3)文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。(4)包含文件的内容必须是C语言的源程序清单。10.2.2文件包含的功能
在编译预处理时,命令行将被包含进来的文件内容替换。
【例10.12】输入半径,计算和显示该半径对应的圆周长、圆面积、球表面积和球体积。分析:将计算圆的周长和面积、球的表面面积和体积的计算公式定义为有参宏,并将这些宏定义单独存放在文件circle.c中。假设文件circle.c和主程序文件都放在D:\TC子目录中。只要在主程序中将circle.c包含进来,就可以直接调用这些宏来计算。(1)主程序文件模块circle.c#include"stdio.h"
#include"circle.h"/*主程序文件中包含文件circle.h*/intmain(){floatr;printf("请输入半径r:");scanf("%f",&r);/*输入半径r*/printf("圆周长:%.2f",CIRCLE(r));/*调用宏CIRCLE(r)*/printf("圆面积:%.2f",AREA(r));/*调用宏AREA(r)*/printf("圆表面积:%.2f",SURFICE(r));/*调用宏SURFICE(r)*/printf("圆体积:%.2f\n",VOLUME(r));/*调用宏VOLUME(r)*/return0;}(2)文件模块circle.h#definePI3.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*/程序的运行情况为:请输入半径r:1.0↙圆周长:6.28圆面积:3.14圆表面积:12.57圆体积:6010.3条件编译10.3.1条件编译命令的形式10.3.2条件编译的功能10.3.1条件编译命令的形式1.第一种形式2.第二种形式3.第三种形式1.第一种形式#ifdef标识符程序段1;#else程序段2;#endif其中的标识符通常是一个符号常量,利用定义该符号常量时所给的值来确定条件是否成立。含义是:如果标识符被define命令定义过,则编译时只编译程序段1的内容,否则编译程序段2的内容。命令中的“#else”以及其后的程序段2可以省略。此时形式如下:
#ifndef程序段1;#endif含义是:如果标识符被define命令定义过,则编译时只编译程序段1的内容,否则不编译程序段1。【例10.13】条件编译应用举例一#defineNUMok/*定义NUM代替ok*/#include"stdio.h"#include"stdlib.h"intmain(){structstu{intnum;char*name;charsex;floatscore;}*ps;ps=(structstu*)malloc(sizeof(structstu));ps->num=102;ps->name="Zhangping";ps->sex='M';ps->score=62.5;#ifdefNUM/*如果NUM被define命令定义过,则输出学号和成绩*/printf("Number=%d\nScore=%f\n",ps->num,ps->sc
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 家居创业营销方案(3篇)
- 市政维修施工方案范本(3篇)
- 拦河浮筒施工方案(3篇)
- 旅行餐饮营销方案(3篇)
- 板屋顶保温施工方案(3篇)
- 橱柜墙砖施工方案(3篇)
- 泡沫混凝土柱子施工方案(3篇)
- 游艇销售营销方案(3篇)
- 球馆开业营销方案(3篇)
- 石碣别墅杀虫施工方案(3篇)
- 2024-2025学年北京市西城区德胜中学七年级(下)期中数学试卷及答案解析
- 2026年北京市海淀区高三一模语文试卷(含答案)
- 建筑垃圾减量化监理监督实施细则
- 部编版七年级历史下册第三单元第18课《统一多民族国家的巩固和发展》教学设计
- 2026年北师大版一年级数学下册全册教案
- T∕QAHN 012-2026 质量创新和质量改进活动成果评价准则
- 2026春季中国工商银行辽宁分行校园招聘72人备考题库附答案详解(夺分金卷)
- 2025年制度建设工作总结及2026年工作计划
- (一模)2025~2026学年度苏锡常镇四市高三教学情况调研(一)政治试卷(含答案)
- 国际电信联盟IMT ~2030空口技术性能指标报告核心要点解读
- 三级 模块三 项目九 心理辅导 任务一 正确应对岗位工作压力
评论
0/150
提交评论