条件编译是由一批预处理器指令,通过指定一些限定的条件,有选择性地对源代码进行预处理,从而实现条件编译。后续的编译、链接等过程都是在预处理之后的代码上进行的,所以预处理之后的代码通常要精简很多(这里精简的思想是包含那个引入的头文件的),无意义的编译指令,根据条件编译代码不需要编译的代码,还有注释都会有预处理之后忽略掉。常用的预的处理器指令主要有(方括号中为后面需要跟的内容):
#空指令: 无意义,预处理时会被忽略
#include [file_name]: 包含一个源代码文件,通常是头文件
#define [args] [可选的常量]: 定义宏
#undef [args]:取消已定义的宏
#if [args]: 如果给定条件为真,则编译下面代码,args必须是已定义的常量宏,或者未定义
#ifdef [args]:如果宏已经定义,则编译下面代码
#ifndef [args]:如果宏没有定义,则编译下面代码
#elif [args]:如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
#endif:结束一个#if……#else条件编译块
#error [sentence]:停止编译并显示错误信息
#line [number] [file_name]:修改变量LINE和FILE的值
注意有两个特殊的运算符:#运算符和##运算符
下面以代码举例:
头文件:
macro.h
1 2 3 4 5 6 7
| #ifndef MACRO_H #define MACRO_H #include <iostream> #
#endif
|
源文件:
macro.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #include "macro.h"
#define PI 3.1415926 #define CUBE(x) (x)*(x)*(x) #define AGE(x) "My age is " #x #define CON(x, y, z) x##y##z #define DEBUG 0 #define RUN 1 #define NODEBUG #define IS_COMPILE #undef IS_COMPILE
int main(void) { std::cout << PI << std::endl; std::cout << CUBE(PI + PI) << std::endl; std::cout << AGE(25) << std::endl; std::cout << CON(18, 19, 20) << std::endl;
#if DEBUG std::cout << "Debug" << std::endl; #elif RUN std::cout << "Run" << std::endl; #else std::cout << "NONE" << std::endl; #endif
#ifdef NODEUBG std::cout << "NoDebug" << std::endl; #endif
#ifdef IS_COMPILE std::cout << "is compile" << std::endl; #endif
#ifndef NODEUBG std::cout << "no NoDebug" << std::endl; #endif
#line 15 "my_macro.cpp"
#if !defined(__cplusplus) #error C++ compiler required. #endif
return 0; }
|
上述代码通过g++ 4.8.4预处理(命令是g++ -E -std=c++11 macro.cpp)之后的代码如下(忽略掉包含的头文件iostream部分):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| # 1 "macro.cpp" # 1 "<built-in>" # 1 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 1 "<command-line>" 2 # 1 "macro.cpp"
# 1 "macro.h" 1 # 10 "macro.h" # 1 "/usr/include/c++/4.8/iostream" 1 3 # 36 "/usr/include/c++/4.8/iostream" 3 # 37 "/usr/include/c++/4.8/iostream" 3
# 1 "/usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h" 1 3 # 184 "/usr/include/x86_64-linux-gnu/c++/4.8/bits/c++config.h" 3
# 11 "macro.h" 2 # 9 "macro.cpp" 2 # 18 "macro.cpp" int main(void) { std::cout << 3.1415926 << std::endl; std::cout << (3.1415926 + 3.1415926)*(3.1415926 + 3.1415926)*(3.1415926 + 3.1415926) << std::endl; std::cout << "My age is " "25" << std::endl; std::cout << 181920 << std::endl;
std::cout << "Run" << std::endl; # 38 "macro.cpp" std::cout << "no NoDebug" << std::endl; # 15 "my_macro.cpp"
return 0; }
|
可以看到代码中少了很多预处理器不需要处理的代码,而且里面已经没有任何预处理指令了,所有剩下的代码都是必须编译并执行的代码。而且return 0的前面一句显示出行号和文件名被#line改成了15、my_macro.cpp