编译预处理程序

编译器在编译源程序以前,要由预处理程序对源程序文件进行预处理。预处理程序提供了一些编译预处理指令和预处理操作符。预处理指令都要由“#”开头,每个预处理指令必须单独占一行,而且不能用分号结束,可以出现在程序文件中的任何位置。

       1.#include指令

       #include指令也叫文件包含指令,用来将另一个源文件的内容嵌入到当前源文件该点处。其实我们一般就用此指令来包含头文件。#include指令有两种写法:

       #include <文件名>

       使用这种写法时,会在C++安装目录的include子目录下寻找<>中标明的文件,通常叫做按标准方式搜索。

       #include "文件名"

       使用这种写法时,会先在当前目录也就是当前工程的目录中寻找""中标明的文件,若没有找到,则按标准方式搜索。

 2.#define和#undef指令

       如果你学过C语言,就会知道用#define可以定义符号常量,比如,#define PI 3.14 这条指令定义了一个符号常量PI,它的值是3.14。C++也可以这样定义符号常量,但一般更常用的是在声明时用const关键字修饰。C语言还用#define定义参数宏,来实现简单的函数运算,比如,#define add(x,y) (x+y) 这条指令说明如果我们用到add(1,2)则预处理后就会用(1+2)代替,C++中一般用内联函数来实现。

       #undef用来删除由#define定义的宏,使其不再起作用。

       3.条件编译指令

       用条件编译指令可以实现某些代码在满足一定条件时才会参与编译,这样我们可以利用条件编译指令将同一个程序在不同的编译条件下生成不同的目标代码。例如,我们可以在调试程序时加入一些调试语句,用条件编译指令控制只有在debug模式下这些调试语句才参与编译,而在release模式下不参与编译。

       条件编译指令有5中形式:

       a.第一种形式:

       #if  常量表达式         
                程序正文        //当“ 常量表达式”非零时本程序段参与编译
       #endif

       b.第二种形式:

       #if   常量表达式
                 程序正文1       //当“ 常量表达式”非零时本程序段参与编译
       #else
                 程序正文2       //当“ 常量表达式”为零时本程序段参与编译
       #endif

       c.第三种形式:

       #if 常量表达式1
                 程序正文1        //当“ 常量表达式1”非零时本程序段参与编译
       elif 常量表达式2
                程序正文2        //当“常量表达式1”为零、“ 常量表达式2”非零时本程序段参与编译
        ...
       elif 常量表达式n
                程序正文n        //当“常量表达式1”、...、“常量表达式n-1”均为零、“ 常量表达式n”非零时本程序段参与编译
       #else
                程序正文n+1      //其他情况下本程序段参与编译
       #endif

       d.第四种形式:

       #ifdef 标识符
                程序段1
       #else
                程序段2
       #endif

       如果“标识符”经#defined定义过,且未经undef删除,则编译程序段1,否则编译程序段2。

       e.第五种形式:

       #ifndef 标识符
                  程序段1
       #else
                  程序段2
       #endif

       如果“标识符”未被定义过,则编译程序段1,否则编译程序段2。

       4.define操作符

       define是预处理操作符,不是指令,所以不能用#开头。使用形式为:define(标识符)。如果括号里的标识符用#define定义过,并且没有用#undef删除,则define(标识符)为非0,否则为0。可以这样使用:
        #if !define(HEAD_H)
        #define HEAD_H

       我们在包含头文件时,有时多次重复包含同一个头文件,比如下面这种情况:

        // main.cpp文件
       #include "file1.h"
       #include "file2.h"
       int main()
       {
              …
       }
       // file1.h文件
       #include "head.h"
        …
       // file2.h文件
       #include "head.h"
        …
       // head.h文件
        ...
       class A
       {
              ...
       }
       ...

       main.cpp包含了file1.h文件,file1.h又包含了head.h文件,main.cpp还包含了file2.h文件,file2.h也包含了head.h文件,那么main.cpp就包含了两次head.h文件,在编译时就会报错,说head.h中的类A重复定义了。这时我们可以在被重复包含的文件head.h中使用条件编译指令,用一个唯一的标识符来标识head.h文件是否已经编译过,如果已经编译过则不会重复编译了。鸡啄米给大家改写下上面的head.h文件:

       // head.h文件
       #ifndef HEAD_H
       #define HEAD_H
       ...
       class A
       {
            ...
       }
       ...
       #endif

       在这个改好的head.h文件中,上来会先判断HEAD_H是否被定义过,如果没有被定义过,则head.h文件还没参与过编译,就编译此文件中的源代码,同时定义HEAD_H,标记head.h文件已经参与过编译。如果HEAD_H已经被定义过,则说明此文件已经参与过编译,编译器会跳过本文件左右内容编译其他部分,类A也不会有重复定义的错误了。

posted on 2020-11-06 08:12  大湾  阅读(457)  评论(0编辑  收藏  举报

导航