C++预处理命令有三种:宏定义命令、文件包含命令、条件编译命令。这些命令在程序中都是以“#”来引导的,每条预处理指令必须单独占用一行,但在行尾不允许有分号“;”。
1.宏定义命令
使用#define定义
1).常量定义
#define PI 3.1415926
这里的#define就是宏定义命令,编译器在处理这个代码之前会对PI进行处理替换为3.1415926,PI称为宏名。
通常宏名定义为大写,以便与普通标识符区别。
宏被定义后,通常不允许再重新定义,只有使用 #undef 命令才可以重新定义。
一个定义过的宏可以用于定义其他新的宏。
这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为#define的定义更像是简单的文本替换,而不是作为一个量来使用。
2).带参数定义
#define MIN(A,B)((A)<=(B)?(A):(B))//两个参数返回较小的一个
其中,(A,B)是宏MIN的参数表
3).单行定义
#define HDY_HR_JSON "HDY_HR.json"
4).多行定义
#define CHECK_CANCEL_AND_QUIT() if (类名::函数名())\
return;
2.文件包含定义
文件包含定义是指将另一个源文件的内容合并到源程序中。C++语言提供了#include命令用于实现文件包含的操作,它有两种格式:
#include <xxx.h>
#include "xxx.h"
文件名通常以“.h”为扩展名,将其称为“头文件”。
#include <xxx.h>与#include "xxx.h"有什么区别?
第一种编译器从标准库路径开始搜索xxx.h。
第二种编译器从用户工作路径开始搜索xxx.h。
3.条件编译命令
一般情况下,源程序中所有的语句都参加编译,但有时也希望根据一定条件去编译源文件的不同部分,即“条件编译”。条件编译使得同一源程序在不同条件下得到不同的目标代码。
格式1:
#ifdef <标识符>
<程序段1>
[
#else
<程序段2>
]
#endif
其中,#ifdef、#else、#endif都是关键字,<程序段>是由若干条预处理命令或语句组成。这种形式的含义是,如果标识符已被#define命令定义过,则编译<程序段1>,否则编译<程序段2>。
格式2:
#ifndef <标识符>
<程序段1>
[
#else
<程序段2>
]
#endif
与格式1的区别是,如果标识符没有被#define命令定义过,则编译<程序段1>,否则编译<程序段2>。
格式3:
#if <表达式1>
<程序段1>
[
#elif <表达式2>
<程序段2>
...
]
[
#else
<程序段n>
]
#endif
其中,#if、#elif、#else、#endif为关键字。含义是,如果<表达式1>为“true”,编译<程序段1>;否则如果<表达式2>为“true”,编译<程序段2>,…;如果表达式都不为“true”,编译<程序段n>。
扩展:防止头文件被重复引用
第一种:
#ifndef _NAME_H
#define _NAME_H
//头文件内容
#endif
其中,_NAME_H 是宏的名称。需要注意的是,这里设置的宏名必须是独一无二的,不要和项目中其他宏的名称相同。
当程序中第一次 #include 该文件时,由于 _NAME_H 尚未定义,所以会定义 _NAME_H 并执行“头文件内容”部分的代码;
当发生多次 #include 时,因为前面已经定义了 _NAME_H,所以不会再重复执行“头文件内容”部分的代码。
第二种:
#pragma once
将其附加到指定文件的最开头位置,则该文件就只会被 #include 一次。
我们知道,#ifndef 是通过定义独一无二的宏来避免重复引入的,这意味着每次引入头文件都要进行识别,所以效率不高。
但考虑到 C 和 C++ 都支持宏定义,所以项目中使用 #ifndef 规避可能出现的“头文件重复引入”问题,不会影响项目的可移植性。
和 ifndef 相比,#pragma once 不涉及宏定义,当编译器遇到它时就会立刻知道当前文件只引入一次,所以效率很高。
但值得一提的是,并不是每个版本的编译器都能识别 #pragma once 指令,一些较老版本的编译器就不支持该指令(执行时会发出警告,但编译会继续进行),即 #pragma once 指令的兼容性不是很好。
目前,几乎所有常见的编译器都支持 #pragma once 指令,甚至于 Visual Studio 2017 新建头文件时就会自带该指令。可以这么说,在 C/C++ 中,#pragma once 是一个非标准但却逐渐被很多编译器支持的指令。
除此之外,#pragma once 只能作用于某个具体的文件,而无法向 #ifndef 那样仅作用于指定的一段代码。