第5章编译预处理.ppt

上传人:sccc 文档编号:5335187 上传时间:2023-06-27 格式:PPT 页数:18 大小:476.01KB
返回 下载 相关 举报
第5章编译预处理.ppt_第1页
第1页 / 共18页
第5章编译预处理.ppt_第2页
第2页 / 共18页
第5章编译预处理.ppt_第3页
第3页 / 共18页
第5章编译预处理.ppt_第4页
第4页 / 共18页
第5章编译预处理.ppt_第5页
第5页 / 共18页
点击查看更多>>
资源描述

《第5章编译预处理.ppt》由会员分享,可在线阅读,更多相关《第5章编译预处理.ppt(18页珍藏版)》请在三一办公上搜索。

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

2、 宏名 字符串 功能:用指定标识符(宏名)代替字符序列(宏体)定义位置:任意(一般在函数外面)作用域:从定义命令到文件结束#undef 可终止宏名作用域 格式:#undef 宏名 宏展开:预编译时,用宏体替换宏名-不作语法检查 引号中的内容与宏名相同也不置换 宏定义可嵌套,不能递归 宏定义中使用必要的括号(),如:#define YES 1#define NO 0#define PI 3.1415926#define OUT printf(Hello,World);,可缺省,表示宏名定义过或取消宏体,如:#define YES 1#define NO 0 if(x=YES)printf(cor

3、rect!n);else if(x=NO)printf(error!n);展开后:if(x=1)printf(correct!n);else if(x=0)printf(error!n);,例:#define PI 3.14159 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;,(),(),5.2 宏定义,【例 5.1】给出下面

4、宏替换的结果#define R 5.0#define FORMAT Area=%fn#define PI 3.14159#define AREA R*R*PI#define PR printf#include 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.2 宏定义,带参数宏定义 一般形式:#define 宏名(参数表)宏体 宏展开:形参用实参换,其它字符保留例:#defin

5、e S(a,b)a*b area=S(3,2);宏展开:area=3*2;宏名与左圆括号之间不能留有空格例:#define S(r)PI*r*r 相当于定义了不带参宏 S,代表字符串“(r)PI*r*r”宏体及各形参外一般应加括号(),例:#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);,5.2 宏定义,【例 5.2】用带参数宏定义求两个数的最大值#define MAX(x,y)(x)(y)?(x):(y)#include main()int

6、 a,b,c;float x,y,z;scanf(%d%d,宏展开:c=(a)(b)?(a):(b),宏展开:z=(x)(y)?(x):(y),运行程序,输入:3 87 12.5 23.8 输出结果为:c=87 z=23.799999,5.2 宏定义,带参的宏与函数区别,5.2 宏定义,在定义和使用宏调用时应该注意的问题 参数多次计算。运算符优先级引起的问题。宏定义中的字符串相连。在定义无参宏时,如果“语言符号字符串”是一个常量,则相应的“宏名”就是一个符号常量。#define EOF-1/*文件尾*/#define NULL 0/*空指针*/使用宏定义的优点 可提高源程序的可维护性 可提高源

7、程序的可移植性 减少源程序中重复书写字符串的工作量,定义:#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,与题意不符。应加括号该定义为:#define squar

8、e(x)(x)*(x),#define s1 12345#define s2 67890#define s s1 s2/*命令连接 s1 和 s2,s 为1234567890,s1 和 s2 之间的空格可有多个*/C 语言中,顺序书写的两个字符串间仅由空格、换行符或制表符分隔,编译时,自动将这两个字符串连接成一个长字符串。,5.3 文件包含,5.3 文件包含(P101)概念 用#include 开始的预处理命令称文件包含命令。文件包含是指,一个源文件可以将另一个源文件的全部内容包含进来。一般格式#include“文件名”或#include 预处理过程 按规定方法寻找文件,若找到,用被包含文件的

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

10、 n 个文件,则要用 n 条包含命令。文件包含可以嵌套,即被包含文件中又包含另一个文件。,5.3 文件包含,包含文件修改后,包含该文件的源程序必须重新编译。前面例子中使用#include 命令包含的是系统标准库的各种头文件(如 stdio.h、math.h),这些头文件的主要内容是标准库函数的原型说明、一些系统使用的符号常量定义等。用#include 命令将这种文件包含进程序,相当于在源程序的前面书写了这些函数原型,这对于保证编译程序能够正确地完成对标准库函数的有关调用是非常重要的。这正是使用#include 命令并将#include 命令写在程序开始处的理由。标准库的所有头文件在 TC 目录

11、的 include 目录下,读者可以打开此目录查看其中的内容,但千万不要试图修改它。,5.3 文件包含,【例5.3】一个包含文件的实例(P101)本例中,format.h 用#define 定义了一组输出格式,在随后的主程序中用这些格式输出若干个变量的值。编辑生成 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

12、.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 2 31 2 3 4,展开为:printf(%d%d n,a,b);,连接为:%d%dn,5.4 条件编译,5.4 条件编译(P102)概念 通常源程序中所有的行都参加编译,但有时希望源程序中的某些行只在满足一定条件下才进行编译,有时又希望满足某一条件时对一组语句进行编译,不满足这一条件时编译另一组语句,这就是“条件编译”。作用 划出源程序的一些片段,使预处理程序可以根据一

13、定条件确定保留或丢掉某个片段,或确定从几个片段中选取哪一个片段保留下来。,5.4 条件编译,三种使用格式根据标识符是否用#define 命令定义过来选择保留程序段1或程序段2。其命令格式如下:,#ifdef 标识符 程序段1#else 程序段2#endif,#ifndef 标识符 程序段1#else 程序段2#endif,上面左右两种形式的选择方法正好相反。,5.4 条件编译,根据表达式值是否为真,选择保留程序段1还是程序段2。其命令格式如下:,#if 表达式 程序段1#else 程序段2#endif,根据多个表达式值,从若干程序段中选取一段。其命令格式如下:,#if 表达式1 程序段1#el

14、if 表达式 2 程序段2#elif 表达式3#else 程序段n#endif,5.4 条件编译,说明条件编译的选取语句操作是在预处理阶段完成的,因此,预处理命令中的表达式都应该是预处理阶段可以求值的表达式。预处理完成之后,所有的预处理命令没有了,得到的是预处理命令展开或选择好的结果。采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,缩短运行时间。条件编译可有效地提高程序的可移植性,并广泛地应用在商业软件中,为一个程序提供各种不同的版本。,5.4 条件编译,【例4.3】一个条件编译实例(P103)调试程序时,经常要打印一些跟踪信息,调试结束后,我们希望这些打印信息不再出现。但是,这些

15、信息对于我们将来修改程序、重新调试相当重要。本例使用条件编译处理这些打印行,使用一个调试宏定义 DEBUG 来实现对调试行的选择控制。条件编译的形式如下:#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);,宏名字用大写字母在源程序中非常醒目。,表达式,4.9 小结,5.5 小结 本章内容不多但很实用,出现的预处理命令有:define,include,if,elif,else,endif,ifdef,idndef。学习本章后应掌握的知识点如下:宏定义的作用,代参宏定义的定义方法,宏调用和函数调用的区别,宏展开的方法。包含命令在多文件程序中的使用,常用头文件及相关函数的使用。条件编译的几种实现方法,如何使用控制条件编译的宏定义。多文件程序的组织和实现方法。,

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

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号