第5章 编译预处理(预编译 条件编译)

上传人:liu****han 文档编号:119645667 上传时间:2022-07-15 格式:PPT 页数:18 大小:478KB
收藏 版权申诉 举报 下载
第5章 编译预处理(预编译 条件编译)_第1页
第1页 / 共18页
第5章 编译预处理(预编译 条件编译)_第2页
第2页 / 共18页
第5章 编译预处理(预编译 条件编译)_第3页
第3页 / 共18页
资源描述:

《第5章 编译预处理(预编译 条件编译)》由会员分享,可在线阅读,更多相关《第5章 编译预处理(预编译 条件编译)(18页珍藏版)》请在装配图网上搜索。

1、1教学内容教学内容教学内容1了解预编译的概念,掌握宏定义的方法。了解预编译的概念,掌握宏定义的方法。2了解了解“文件包含文件包含”与预处理的应用。与预处理的应用。3了解条件编译的几种形式。了解条件编译的几种形式。教学要求教学要求教学要求2 5.1 概述概述5.1 5.1 5.1 概述概述概述概述概述概述(P98)编译预处理是指,在进行编译之前,先对源程序中的编译预处理命令进行处理;然后再将处理的结果,和源程序一起进行编译,以得到目标代码宏定义#define文件包含#include条件编译#if _#else_#endif 等“#”开头占单独书写行语句尾不加分号3 5.2 宏定义宏定义5.2 5

2、.2 5.2 宏定义宏定义宏定义宏定义宏定义宏定义(P98)l 一般形式一般形式:#define 宏名 字符串字符串l 功能功能:用指定标识符(宏名)代替字符序列(宏体)l 定义位置定义位置:任意(一般在函数外面)l 作用域作用域:从定义命令到文件结束l#undef 可可终止宏名作用域终止宏名作用域 格式:#undef 宏名l 宏展开宏展开:预编译时,用宏体替换宏名 -不作语法检查l 引号中的内容与宏名相同也不置换引号中的内容与宏名相同也不置换l 宏定义可嵌套,不能递归宏定义可嵌套,不能递归l 宏定义中使用必要的括号宏定义中使用必要的括号()如:#define YES 1#define NO

3、0#define PI 3.1415926#define OUT printf(Hello,World);可缺省,表示宏名定义过或取消宏体例:#define YES 1 main()#undef YES .#define YES 0 max()YES 原作用域YES 新作用域如:#define YES 1#define NO 0 if (x=YES)printf(correct!n);else if (x=NO)printf(error!n);展开后:if (x=1)printf(correct!n);else if (x=0)printf(error!n);例:#define PI 3.14

4、159 printf(2*PI=%fn,PI*2);宏展开:printf(2*PI=%fn,3.14159*2);例:不能递归不能递归#define MAX MAX+10 ()例:宏定义可嵌套宏定义可嵌套#define WIDTH 80#define LENGTH WIDTH+40 var=LENGTH*2;宏展开:var=80+40 *2;()()4 5.2 宏定义宏定义l【例【例 5.1】给出下面宏替换的结果#define R 5.0#define FORMAT Area=%fn#define PI 3.14159#define AREA R*R*PI#define PR printf#i

5、nclude main()PR(FORMAT,AREA);PR(FORMAT);宏替换的结果宏替换的结果:#include main()printf(Area=%fn,5.0*5.0*3.14.59);printf(FORMAT);运行结果运行结果:Area=78.539750 FORMAT 5 5.2 宏定义宏定义l 一般形式:一般形式:#define 宏名(参数表)宏体l 宏展开:宏展开:形参用实参换,其它字符保留例:#define S(a,b)a*b area=S(3,2);宏展开:area=3*2;l 宏名与左圆括号之间不能留有空格宏名与左圆括号之间不能留有空格例:#define S(

6、r)PI*r*r 相当于定义了不带参宏 S,代表字符串“(r)PI*r*r”l 宏体及各形参外一般应加括号宏体及各形参外一般应加括号()例:#define POWER(x)x*x x=4;y=6;z=POWER(x+y);宏展开:z=x+y*x+y;一般写成:#define POWER(x)(x)*(x)宏展开:z=(x+y)*(x+y);6 5.2 宏定义宏定义l【例【例 5.2】用带参数宏定义求两个数的最大值#define MAX(x,y)(x)(y)?(x):(y)#include main()int a,b,c;float x,y,z;scanf(%d%d,&a,&b);c=MAX(a

7、,b);scanf(%f%f,&x,&y);z=MAX(x,y);printf(c=%d z=%f n,c,z);宏展开宏展开:c=(a)(b)?(a):(b)宏展开宏展开:z=(x)(y)?(x):(y)运行程序运行程序,输入:输入:3 87 12.5 23.8 输出结果为:输出结果为:c=87 z=23.7999997 5.2 宏定义宏定义l 带参的宏与函数区别带参的宏与函数区别带参宏带参宏函数函数处理时间处理时间编译时编译时程序运行时程序运行时参数类型参数类型无类型问题无类型问题定义实参定义实参,形参类型形参类型处理过程处理过程 不分配内存不分配内存简单的字符置换简单的字符置换 分配内存

8、分配内存先求实参值先求实参值,再代入形参再代入形参程序长度程序长度变长变长不变不变运行速度运行速度不占运行时间不占运行时间调用和返回占时间调用和返回占时间8 5.2 宏定义宏定义l 在定义和使用宏调用时应该注意的问题在定义和使用宏调用时应该注意的问题 参数多次计算。运算符优先级引起的问题。宏定义中的字符串相连。l 在定义无参宏时在定义无参宏时,如果如果“语言符号字符串语言符号字符串”是一是一个常量,则相应的个常量,则相应的“宏名宏名”就是一个符号常量。就是一个符号常量。#define EOF -1 /*文件尾*/#define NULL 0 /*空指针*/l 使用宏定义的优点使用宏定义的优点

9、可提高源程序的可维护性 可提高源程序的可移植性 减少源程序中重复书写字符串的工作量 定义:#define min(A,B)(A)(B)?(A):(B)调用1:z=min(x+y,x*y);展开:z=(x+y)(x*y)?(x+y):(x*y);调用2:z=min(n+,m+);展开:z=(n+)(m+)?(n+):(m+);两个调用都出现参数表达式计算多次的问题,可能会成为程序中的隐含错误。定义:#define square(x)x*x 调用:z=square(x+y);展开:z=x+y*x+y;算符“*”的优先级高于“+”的优先级,接开表达式中,将首先计算 y*x,与题意不符。应加括号该定义

10、为:#define square(x)(x)*(x)#define s1 12345#define s2 67890#define s s1 s2 /*命令连接 s1 和 s2,s 为1234567890,s1 和 s2 之间的空格可有多个*/C 语言中,顺序书写的两个字符串间仅由空格、换行符或制表符分隔,编译时,自动将这两个字符串连接成一个长字符串。9 5.3 文件包含文件包含5.3 5.3 5.3 文件包含文件包含文件包含文件包含文件包含文件包含(P101)用#include 开始的预处理命令称文件包含命令。文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。#include “

11、文件名”或#include 按规定方法寻找文件,若找到,用被包含文件的内容取代该预处理命令,再对“包含”后的文件作一个源文件编译;若找不到,则预编译出错,提示无法打开相应文件。直接按标准目录搜索 先在当前目录搜索,再搜索标准目录,可指定路径#include “file2.c”Afile1.cBfile2.c10 5.3 文件包含文件包含 一个大程序,通常分为多个模块,并由多个人分别编程。有了文件包含处理功能,就可以将多个模块共用的数据(如符号常量和数据结构)或函数,集中到一个单独的文件中。这样,凡是要使用其中数据或调用其中函数的人,只要使用文件包含,将所需文件包含进来即可,不必再重复定义它们,

12、从而减少重复劳动。#include 命令行应写在程序的开头。一条包含命令,只能指定一个被包含文件。如果要包含 n 个文件,则要用 n 条包含命令。文件包含可以嵌套,即被包含文件中又包含另一个文件。#include file2.c#include file3.cAfile1.cBfile2.cCfile3.c#include file2.cAfile1.cCfile3.c#include file3.cB结果:ABCfile2.c11 5.3 文件包含文件包含 包含文件修改后,包含该文件的源程序必须重新编译。前面例子中使用#include 命令包含的是系统标准库的各种头文件(如 stdio.h、

13、math.h),这些头文件的主要内容是标准库函数的原型说明、一 些 系 统 使 用 的 符 号 常 量 定 义 等。用#include 命令将这种文件包含进程序,相当于在源程序的前面书写了这些函数原型,这对于保证编译程序能够正确地完成对标准库函数的有关调用是非常重要的。这正是使用#include 命令并将#include 命令写在程序开始处的理由。标准库的所有头文件在 TC 目录的 include 目录下,读者可以打开此目录查看其中的内容,但千万不要试图修改它。12 5.3 文件包含文件包含一个包含文件的实例(P101)本例中,format.h 用#define 定义了一组输出格式,在随后的主

14、程序中用这些格式输出若干个变量的值。编辑生成 format 上的方法与编辑普通 C 源程序一样,保存文件时给它指定合适的名称和后缀就可以了。文件 format.h 如下:#define NL n#define D%d#define D1 D NL#define D2 D D1#define D3 D D2#define D4 D D3主函数如下:#include format.hmain()int a,b,c,d;a=1;b=2;c=3;d=4;printf(D1,a);printf(D2,a,b);printf(D3,a,b,c);printf(D4,a,b,c,d);运行结果:11 21

15、2 31 2 3 4展开为:printf(%d%d n,a,b);连接为:%d%dn 13 5.4 条件编译条件编译5.4 5.4 5.4 条件编译条件编译条件编译条件编译条件编译条件编译(P102)通常源程序中所有的行都参加编译,但有时希望源程序中的某些行只在满足一定条件下才进行编译,有时又希望满足某一条件时对一组语句进行编译,不满足这一条件时编译另一组语句,这就是“条件编译”。划出源程序的一些片段,使预处理程序可以根据一定条件确定保留或丢掉某个片段,或确定从几个片段中选取哪一个片段保留下来。14 5.4 条件编译条件编译l 根据标识符是否用#define 命令定义过来选择保留程序段1或程序

16、段2。其命令格式如下:#ifdef 标识符 程序段1#else 程序段2#endif#ifndef 标识符 程序段1#else 程序段2#endif上面左右两种形式的选择方法正好相反。15 5.4 条件编译条件编译l 根据表达式值是否为真,选择保留程序段1还是程序段2。其命令格式如下:#if 表达式 程序段1#else 程序段2#endifl 根据多个表达式值,从若干程序段中选取一段。其命令格式如下:#if 表达式1 程序段1#elif 表达式 2 程序段2#elif 表达式3#else 程序段n#endif16 5.4 条件编译条件编译l 条件编译的选取语句操作是在预处理阶段完成的,因此,预

17、处理命令中的表达式都应该是预处理阶段可以求值的表达式。预处理完成之后,所有的预处理命令没有了,得到的是预处理命令展开或选择好的结果。l 采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,缩短运行时间。l 条件编译可有效地提高程序的可移植性,并广泛地应用在商业软件中,为一个程序提供各种不同的版本。17 5.4 条件编译条件编译一个条件编译实例(P103)调试程序时,经常要打印一些跟踪信息,调试结束后,我们希望这些打印信息不再出现。但是,这些信息对于我们将来修改程序、重新调试相当重要。本例使用条件编译处理这些打印行,使用一个调试宏定义 DEBUG 来实现对调试行的选择控制。条件编译的形式

18、如下:#define DEBUG 1#if DEBUG /*此处为打印行或调试行*/#endif 调试程序时,DEBUG 定义为1;调试结束,DEBUG 定义为 0。可在所有调试及打印行处加入本例的条件编译命令。下面是一段示例程序:#define DEBUG 1#include main()#if DEBUG printf(This is testing linen);#endif printf(This is normal linen);宏名字用大写字母在源程序中非常醒目。表达式18 4.9 小结小结5.5 5.5 5.5 小结小结小结小结小结小结 本章内容不多但很实用,出现的预处理命令有:define,include,if,elif,else,endif,ifdef,idndef。学习本章后应掌握的知识点如下:l 宏定义的作用,代参宏定义的定义方法,宏调用和函数调用的区别,宏展开的方法。l 包含命令在多文件程序中的使用,常用头文件及相关函数的使用。l 条件编译的几种实现方法,如何使用控制条件编译的宏定义。多文件程序的组织和实现方法。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!