⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c++9.dat

📁 C++指令字典 一个方便的软件 用于C++指令的查询
💻 DAT
字号:
第九章 编译预处理

第一节 宏定义

我们用C++进行编程的时候,可以在源程序中包括一些编译命令,以告诉编译器对源程序如何进行编译.这些命令包括:宏定义、文件包含和条件编译,由于这些命令是在程序编译的时候被执行的,也就是说,在源程序编译以前,先处理这些编译命令,所以,我们也把它们称之为编译预处理,本章将对这方面的内容加以介绍.
  实际上,编译预处理命令不能算是C++语言的一部分,但它扩展了C++程序设计的能力,合理地使用编译预处理功能,可以使得编写的程序便于阅读、修改、 移植和调试.
  预处理命令共同的语法规则如下:
  * 所有的预处理命令在程序中都是以"#"来引导 如"#include "stdio.h"".
  * 每一条预处理命令必须单独占用一行,如"#include "stdio.h" #include <stdlib.h>" 是不允许的.
  * 预处理命令后不加分号,如"#include "stdio.h";" 是非法的.
  * 预处理命令一行写不下,可以续行,但需要加续行符"\".
  下面我们对宏定义、文件包含和条件编译三种预处理命令的用法分别进行介绍.


 宏定义命令将一个标识符定义为一个字符串.如:
  #define CUBE_THREE 3*3*3
  #表示这是一条预处理命令, define为关键字, CUBE_THREE(标识符)称为宏名,也简称为宏, 3*3*3是被定义的字符串.这样, CUBE_THREE就代表字符串3*3*3.当源程序被编译的时候,遇到标识符CUBE_THREE,均以字符串3*3*3进行替换.由于宏定义命令是用于字符串的替换,我们也常把宏名用指定的字符串进行替换的过程,称之为宏替换.
例如:
#include <iostream.h>
//将系统输入输出流头文件包含进来,如果没/有这一行语句,
//用VC编译器进行编译的//话,会出现下面的错误提示:
//error C2065: 'cout' : undeclared identifier 
#define CUBE_THREE 3*3*3
//用简单宏定义定义了一个符号常量"CUBE_THREE"
void main()
{
 int a;
 a=CUBE_THREE;
 //将该宏的值赋给a,实际上是将该宏所定义的符号常量的值赋给a,
 //因此在编译运//行到该语句的时候,"a=CUBE_THREE;"等价于"a=3*3*3;"
 cout<<"a is"<<a<<endl;
 //输出a的值,观察宏替换产生的结果
} 
 
 
  编译并运行该程序,结果如下:
  a is 27
  因为经过宏替换后,语句"a=CUBE_THREE"等价于"a=3*3*3;". 
  宏替换的功能为我们编程时可以带来一些方便.因为,如果在程序中,某一个常量出现较多,就可以为该常量定义一个宏.这样,假定我们要修改该常量时,就不必在程序中对该常量用手工一个个地查找、修改,而只要修改其宏定义即可.例如,如果在一个程序里,3的立方出现的次数比较多,我们就可以把它定义成上面的宏的形式.假定现在需要把3的立方修改成3的4次方,只要修改宏定义即可:
  #define CUBE_THREE 3*3*3*3
  宏定义命令通常有两种格式:一种是简单的宏定义,另一种是带参数的宏定义.

 1.1 简单的宏定义
  上面的实例就是一个简单的宏定义,简单宏定义的一般形式如下:
  #define <宏名> <字符串>
  其中, define是宏定义命令的关键字,<宏名>是一个标识符,<字符串>可以是常数、表达式、格式串等.
  在程序被编译的时侯,如果遇到宏名,先将宏名用指定的字符串替换,然后再进行编译.

 1.2 带参数的宏定义
  带参数的宏定义的一般形式如下:
  #define <宏名>(<参数表>) <宏体>
  其中, <宏名>是一个标识符,<参数表>中的参数可以是一个,也可以是多个,视具体情况而定,当有多个参数的时候,每个参数之间用逗号分隔.<宏体>是被替换用的字符串,宏体中的字符串是由参数表中的各个参数组成的表达式.例如:
  #define SUB(a,b) a-b
如果在程序中出现如下语句:
  result=SUB(2, 3)
则被替换为:
  result=2-3;
如果程序中出现如下语句:
  result= SUB(x+1, y+2);
则被替换为:
  result=x+1-y+2;
  在这样的宏替换过程中,其实只是将参数表中的参数代入到宏体的表达式中去,上述例子中,即是将表达式中的a和b分别用2和3代入.
  我们可以发现:带参的宏定义与函数类似.如果我们把宏定义时出现的参数视为形参,而在程序中引用宏定义时出现的参数视为实参.那么上例中的a和b就是形参,而2和3以及x+1和y+2都为实参.在宏替换时,就是用实参来替换<宏体>中的形参.

第二节 文件包含

 
  文件包含命令格式如下:
  #include <文件名>
或者
  #include "文件名"
其中,include是关键字,文件名是指被包含的文件全名.在前面我们已多次用此命令包含过库函数的头文件.例如:"#include "stdio.h"".
  文件包含命令的功能是把指定的文件插入该命令行位置,从而把指定的文件和当前的源程序文件连成一个源文件.在C++的程序设计中,文件包含命令用得很多.我们常将符号常量、类及其它类型的定义放到一个.h文件中(即文件扩展名为h的文件,称之为头文件).在其它文件的开头用包含命令包含该头文件,这样就可以减少重复劳动,节省时间,并减少出错的可能性.头文件可以是自己编写的,也可以是系统提供的.例如,前面程序中已出现的iostream.h便是一个系统提供的、有关输入输出操作信息的头文件.
  上面我们看到,文件包含命令的格式有两种,一种将文件名以尖括号(< >)括起,另一种是将文件名以双引号("")括起.这两种格式的用法略有区别:使用前一种格式,在编译的时候将会在指定的目录下查找此头文件,而使用后一种格式,在编译的时侯会首先在当前的源文件目录中查找该头文件,若找不到才会到系统的指定目录下去查找.
  在定义和使用文件包含时还应注意以下几点:
  (1)一条文件包含命令只能包含一个文件,若想包含多个文件须用多条文件包含命令.例如: 
  #include<iostream.h>
  #include<stdio.h>
  …
  (2)文件包含命令可以嵌套使用,即在一个被包含的文件中可以包含另一个文件.例如,定义一个头文件,其名字为headfilel.h,该文件内容如下:
  #include "headfile2.h"
  #include "headfile3.h"
  …
这里即嵌套使用了文件包含命令.

 
第三节 条件编译

条件编译命令可以使得编译器按不同的条件去编译程序不同的部分,产生不同的目标代码文件.也就是说,通过条件编译命令,某些程序代码要在满足一定条件下才被编译,否则将不被编译.
  常用的条件编译命令有如下三种格式: 

 3.1 格式一
  #ifdef 标识符
   程序段1
  #else
   程序段2
  #endif 
  其中,ifdef、else和endif都是关键字.程序段1和 程序段2是由若干预处理命令和语句组成的.它的功能是,如果标识符已被 #define命令定义过,则对程序段1进行编译;否则对程序段2进行编译.本格式中的#else也可以没有:
  #ifdef 标识符 
   程序段 
  #endif 

 3.2 格式二
  #ifndef 标识符
   程序段1 
  #else
   程序段2
  #endif 
  格式二和格式一形式上的的区别在于ifdef关键字换成了ifndef关键字,其功能是:如果标识符未被#define命令定义过,则对程序段1进行编译, 否则对程序段2进行编译,这与格式一的功能正好相反.例如:
  #ifndef NULL
  #define NULL ((void *)0)
  #endif
本段代码能够保证符号NULL只有一次定义为((void *)0).

 3.3 格式三
  #if 常量表达式
   程序段1
  #else
   程序段2
  #endif 
  if、else和endif是关键字.程序段1、程序段2都是由若干条预处理命令和语句组成.它的功能是:如常量表达式的值为真(true),则对程序段1 进行编译,否则对程序段2进行编译.因此可以使程序在不同条件下,完成不同的功能.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -