资源预览内容
第1页 / 共50页
第2页 / 共50页
第3页 / 共50页
第4页 / 共50页
第5页 / 共50页
第6页 / 共50页
第7页 / 共50页
第8页 / 共50页
第9页 / 共50页
第10页 / 共50页
亲,该文档总共50页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
编译预处理在语言中包含一类特殊的命令(或称指令) ,这类特殊命令的作用不是直接实现程序的功能, 而是为语言编译系统提供信息,这些信息将通知 语言编译器在对源程序进行正式编译之前应该做 什么,这一类特殊的命令被称为“编译预处理命令 ”。语言的预处理程序是语言编译系统的组成 部分,它负责分析和处理程序中使用的几种预处理 命令,由于预处理程序对这些预处理命令的处理是 在编译程序的其它部分处理之前进行的,因此,把 这些命令称为预处理命令。正确地使用编译预处理命令,能够编写出易于 调试、易于移植的程序,并能为模块化程序设计提 供帮助。语言提供的预处理命令有如下几种: (1)宏定义(2)文件包括(3)条件编译 注 意:为了与一般的语言语句相区别,所有的预 处理命令都是以符号“#”开始的。10.1 宏定义一种是符号常量定义,另一种是带参数 的宏定义。语言的宏定义可以分为两种形式:1 .符号常量定义一般来讲,程序中所使用的常量(或称常数)都 具有一定的意义,但如果在程序中直接使用常量本身 ,却很难看出它的意义。为了提高程序的可读性, 语言提供了用于定义符号常量(即用一个符号来代替 一个常量)的预处理语句。 符号常量的定义 #define 符号常量名 字符串 符号常量名习惯上用大 写字母表示,符号常量 名与所对应的字符串之 间用“空格”符隔开。 在程序中,凡是出现符号常量名的地方,经 过编译预处理程序的加工后,都被替换成它所对 应的字符串。这一替换过程被称为宏展开。说 明例 如 #define ESC 0x1B它定义了符号常量ESC所对应的常量是 0x1B,这样,在正式编译之前,程序中出 现的所有符号常量ESC,都将被预处理程 序以常量0x1B代替。 显然,当ESC的编码值有变化时,只要修改宏 定义语句即可,而程序的其余部分则不需要做任 何修改,这样,利用宏定义编写的程序,将有助 于程序的调试和移植。 【例7.1】从键盘输入不超过100个字符,并统计其中英文 字母(不区分大小写)的个数,直到输入的字符为*或 输入的字符个数超过100为止。#include “stdio.h“ #define MAXnum 100 void main( ) int i,count=0;char c;for(i=0; i= a scanf(“%d%d“,z=MAX(x,y);printf(“Max=%d“,z);在使用带参数的宏定义时,需要注意如下几个问题:(1)一般来讲,对宏定义字符串中的参数都要用括号括起 来,整个字符串部分也应该用括号括起来,这样,才能够保证 在任何替代情况下,总是把宏定义作为一个整体来看待,并能 获得一个合理的计算顺序,否则,经过宏展开后,有可能出现 意想不到的错误。 例如,下面的宏定义是用于求平方值的:#define SQR(A) A*A如果在程序中有下面的赋值语句:z=SQR(x+1)*2;经预处理程序宏展开后,将变为如下形式:z=x+1*x+1*2; 应将SQR宏定义改成如下形式:#define SQR(A) (A)*(A)(2)不难看出,带参数的宏定义也可以由函数 来实现,由于程序中每使用一次宏都要进行一次替 代操作,所以,如果在程序中多次使用宏,程序的 目标代码可能比使用函数要长一些。一般用宏来表 示一些简单的表达式。 10.2 文件包括文件包括(又称文件包含)是指一个源文件可以 将另外一个指定的源文件包括进来。 文件包括的一般形式#include 或:#include “文件名“在使用#include命令时,如果“文件名“部分是用双引号 括起来的,则编译系统首先在源程序文件所属的文件目录 中寻找所包括的文件,如果没有找到,再按系统指定的标 准方式检索其它目录;如果部分是用尖括号( )括起来的,则编译预处理程序只按系统指定的标准方式 来检索文件目录。因此,使用双引号的#include命令的检索 路径,将包含使用尖括号的#include命令的检索路径。 例 如int i1,i2,i3;float f1,f2,f3; char c1,c2,c3;#include “file1.cpp“main( )若file1.cpp文件内容为:file2.cpp文件为:则编译预处理后,file2.cpp文 件中的内容为: int i1,i2,i3; float f1,f2,f3; char c1,c2,c3; main( ) 在语言编译系统中有许多以.h为扩展名的文件 ,这些文件一般被称为“头文件”,在使用语言 编译系统提供的库函数进行程序设计时,通常需要 在源程序中包括进来相应的“头文件”,在这些“ 头文件”中,对相应函数的原型及符号常量等进行 说明和定义。 例 如在使用语言库函数进行输入、输出操作时,一般需 要在源程序中使用如下形式的文件包括预处理命令: #include “stdio.h“使用#include命令需要注意的问题(1)当#include命令指定的文件中的内容发生 改变时,包括这个文件的所有源文件都应该重新 进行编译等处理。(2)文件包括可以嵌套使用,即被包括的文 件中还可以使用#include命令来包括其它文件。 (3)由#include命令所指定的文件中可以包 含任何语言成分,通常将经常使用的、具有公用 性质的符号常量、带参数的宏定义以及外部变量 等集中起来放在这种文件中,这样可避免一些重 复操作。(4)被包括的文件通常是源文件,而不是目 标文件。10.3 条件编译语言的编译预处理程序还提供了条件编译能 力,它使得同一个源程序在不同的编译条件下能够 产生不同的目标代码文件。灵活地运用这一功能, 将有助于程序的调试和移植。 条件编译命令有以下几种形式: #ifdef,#else和#endif其一般形式如下所示: #ifdef 标识符程序段1 #else程序段2 #endif 作用:如果标识符已经定义过则程序段1参加编译,否则,程序段2参加 编译。程序段1和程序段2可以包含任意条语句。程序段1或程序段2即使 由多条语句组成,也不需要用花括号括起来。其中#else部分可以省略,即: 作用:如果标识符已经定义过,则程序段部分参加编译,否 则,程序段部分不参加编译。#ifdef 标识符程序段 #endif需要注意的是,#ifdef和#endif一定要配对使用。有的计算机存放一个整数需要16位(2个字节),而有的计算机 存放一个整数需要32位(4个字节),为了使所编写的程序具 有通用性,在程序中可以使用如下的条件编译命令: #ifdef NEC_PC #define INT_SIZE 16 #else #define INT_SIZE 32 #endif例如如果NEC_PC在前面定义过,即有如下命令:#define NEC_PC 1 或:#define NEC_PC则将编译下面的命令:#define INT_SIZE 16否则,将编译下面的命令:#define INT_SIZE 32这样,在源程序不作修改的情况下,只要增加命令#define NEC_PC或删除该命令,就可以使该程序运行于不同的计算机系统。条件编译语句的设置,还有利于对程序的 调试。例如,在调试程序时,常常需要查看程 序运行的中间结果,通常的作法是在程序的相 应位置上插入一些显示语句,程序调试完成后 ,再将这些用于显示中间结果的临时语句删掉 ,显然,当程序中多处使用这种语句时,这种 作法是很麻烦的。 如果使用条件编译命令将简单得多,可以在 程序的相应位置上插入下面的条件编译命令: #ifdef DEBUG printf(“X=%d, Y=%dn“, x, y); #endif如果在上述语句的前面DEBUG已经定义过,即有如下命令: #define DEBUG则在程序运行时将显示相应位置上的x、y的值,程序调试完成 后,只要删去DEBUG的定义命令并重新进行编译和连接操作 ,上述printf语句就不参加编译,这样它就不起作用,程序运 行时将不再显示x、y的中间结果。不参加编译的语句尽管在源程序中存在,但 在目标程序中并没有与之对应的代码,因此,条 件编译命令同语言中的if语句是有区别的。#ifndef命令一般形式如右所示: 2. #ifndef命令#ifndef 标识符程序段1#else程序段2#endif作用:当标识符没有定义 时,编译程序段1,否则 ,编译程序段2 。#else部分可以省略 :#ifndef 标识符程序段#endif作用:当标识符没 有定义时,程序段 部分参加编译,否 则,程序段部分不 参加编译。注意:#ifndef和#endif一定要配合使用。#ifndef NEC_PC #define INT_SIZE 32 #else #define INT_SIZE 16 #endif当NEC_PC没有定义时:#define INT_SIZE 32 参加编译(起作用),否则: #define INT_SIZE 16 参加编译(起作用)。例如:功能:3. #if 命令#if预处理命令提供了按条件控制编译过程的更 一般的方法。其一般使用方法如下所示: #if 表达式1程序段1 #else程序段2 #endif作用:当表达式1为 “真”(值非0)时, 程序段1参加编译, 否则,程序段2参加编译。其中的 #else部分可以省略。注意:#if和#endif一定要配合使用。 #define FLAG 1 #if FLAGx=1; #elsex=0; #endif例如:表示:如果FLAG为“真”(值非0),则编译语句:x=1; 即将1赋给x; 否则,如果FLAG为“假”(值为0),则编译语句:x=0; 即将0赋给x。#define MEMSIZE 640 #if MEMSIZE=640char buffer3000; #elsechar buffer1000; #endif例 如注意:#if预处理命令中的 表达式是在编译阶段求值 的,因此,它们必须是常 量表达式或是利用#define 命令定义的标识符,而不 能是变量。 4. #undef 命令#undef命令的一般形式如下所示: #undef 标识符作用是将已经定义的标识符 变为未定义的。#undef DEBUG例 如#ifdef DEBUG 为“假” #ifndef DEBUG 为“真”将已被定义的标识符 DEBUG变为未定义的导致【例7.3】从键盘输入10个整型数据,并根据所设置的 编译条件,将其中的最大值或最小值显示出来。#include “stdio.h“#define MFLAG 1void main( )int i,M;int array10;for(i=0;iarrayi)M=arrayi;#endif if(MFLAG)printf(“Max=%d“,M);elseprintf(“Min=%d“,M);说 明if(Marrayi)M=arrayi;当定义MFLAG为0时,for循环中的语句:参加编译,此时求10 个数中的最小值。【例7.4】从键盘输入三个整数,并利用宏定义求 出其中的最小值。 #include “stdio.h“#define MIN(x,y) (x) (y) ? (x) : (y)void main( )int a,b,c,M;printf(“Input a,b,c:“);scanf(“%d%d%d“,M=MIN(MIN(a,b),c);printf(“Min=%d“,M);
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号