【c++】编译预处理
1、文件包含 #include
2、宏定义(宏替换) #define
3、条件编译指令 #ifdef
参考:
《c++从入门到精通》人民邮电出版社
详解C/C++预处理器 https://blog.csdn.net/huang_xw/article/details/7648117
预处理程序又称预处理器,它包含在编译器中。 C/C++编译系统编译程序的过程为预处理、编译、链接。预处理器是在程序源文件被编译之前根据预处理指令对程序源文件进行处理的程序。
预处理程序对源文件进行第一次处理,它处理的是预处理命令。c++提供的预处理命令主要是三种:
文件包含命令
宏定义命令
条件编译
预处理器指令以#号开头标识,末尾不包含分号。预处理命令不是C/C++语言本身的组成部分,不能直接对它们进行编译和链接。
1、文件包含 #include
预处理指令#include用于包含头文件,有两种形式:
#include<xxx.h> (尖括号形式表示被包含的文件在系统目录的include子目录中)
#include "xxx.h" (双引号形式一般表示用户自己编写的头文件)
第一种,这些头文件一般存在于c++系统目录的include子目录中。C++预处理器程序遇到这条命令后,就到include子目录中搜索给出的文件,并把它嵌入到当前文件中。这种形式也是标准形式。
第二种,适用于用户自己编写的头文件。在双引号形式中可以指出文件路径和文件名。如果在双引号中没有给出绝对路径,则默认为用户当前目录中的文件,此时系统首先在用户当前目录中寻找要包含的文件,若找不到再在系统目录中查找。
2、宏定义(宏替换) #define
#define 用来进行宏定义。宏定义包括不带参数宏定义和带参数宏定义两种。
(1)不带参数的宏定义
形式:#define 标志符 字符串
例如:#define PI 3.1415926
作用:用一个标识符去代替一个字符串。在编译时,将宏名替换成字符串的过程称为“宏展开”。
优点:使用宏定义可以减少程序中重复书写某些字符串的工作量,也可以减少出错率。
作用域:宏定义的有效范围称为宏名的作用域,宏名的作用域从宏定义的结束处开始到其所在的源代码文件末尾。如果需要终止宏名的作用域,可以用预处理指令#undef加上宏名。
注意:宏定义只做字符替换,不分配内存空间。宏替换不占运行时间,只占用编译时间。
(2)带参数的宏定义
形式:#define 宏名(参数表) 字符串
例如:#define S(a,b) a*b
area=S(2,3);
展开过程:按#define命令中指定的字符串从左到右进行替换。
注意:带参数的宏定义类似于函数,在调用时,形参与实参一一对应,与函数调用的方法相似。但二者有本质区别:函数调用时,要先求出实参表达式的值,然后带入形参;而宏定义只是单纯的进行字符串替换,不涉及运算。
在c语言中,#define用来建立常量,或者定义带参数的宏。而在c++中仍然保留了这些特征,但是经常用const语句代替不带参数的宏,用inline内联函数代替带参数的宏。
3、条件编译指令 #ifdef
一般情况下,在进行编译时对源程序中的每一行都要编译,但是有时希望程序中某一部分内容只在满足一定条件时才进行编译,如果不满足这个条件,就不编译这部分内容,这就是条件编译。
条件编译主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到多个版本控制、防止对文件重复包含的功能。#if,#ifndef,#ifdef,#else,#elif,#endif是比较常见条件编译预处理指令,可根据表达式的值或某个特定宏是否被定义来确定编译条件。
① 指令意义
#if 表达式非零就对代码进行编译;
#ifdef 如果宏被定义就进行编译;
#ifndef 如果宏未被定义就进行编译;
#else 作为其它预处理的剩余选项进行编译;
#elif 这是一种#else和#if的组合选项;
#endif 结束编译块的控制。
② 常用形式
#if_#endif形式:
#if 常数表达式 或 #ifdef 宏名 或 #ifndef 宏名
程序段
#endif
如果常数表达式为真(//该宏名已定义//该宏名未定义),则编译后面的程序段;否则就不编译,跳过这段程序。
------------------------------------------- END -------------------------------------