贡献者: addis
#
(前后都可以有空格) 的叫做预处理指令(preprocessor directive),是给预编译器看的。预编译器同样会无视注释。
#include 头文件
指令就是让预编译器把头文件中的代码原封不动地插入到当前位置。
cpp
文件其实都是单个文件,无论它的 include 有多复杂。
#define 宏名 代码
把一个宏定义为一串别的代码。代码
如果要换行,可以用 \
。
\
紧接一个换行符” 进行删除处理,哪怕它在字符串中间或者变量名中间(但这是很不推荐的)。况且许多地方换行并不需要什么特殊符号,所以这个功能一般用于把一个较长的宏写为多行。所以对预编译器来说,每个 preprocessor directive 仍然只能有一行(它看不到 \
)。
#define 宏名
仅仅定义一个宏,也可以理解为 代码
为空。
前缀_宏名
,如果你在写库,通常这个前缀是库的名字。
#ifdef 宏 ... #else ... #endif
可以判断宏是否存在,类似地,有 #ifndef 宏
。(注意每一个 #
都要换行。
#if 条件 ... #elif ... #else ... #endif
。例如条件可以是 #if defined(宏)
相当于 #ifdef
,#if !defined(宏)
相当于 #ifndef
。预编译器会删除不满足条件的 ...
中的代码,编译器将看不到它的存在。
#if ... #elif ... #endif
之间的其他宏全部缩进,如果不缩进也可以用注释表明对应关系。
defined()
函数是一个特殊的存在,没有其他类似的函数了(除了下文的宏函数)。
&&
,||
,可以用括号,可以用 >, <=, ==, !=
等比较数值的大小,可以用 +,-,*,/,%
等算符。注意运算和比较仅限于整数。
#if sizeof(Int) == 4
g++ -E 源文件.cpp
可以输出预编译的结果(将把所有宏都进行替换)。
#undef 宏
可以在之后的代码中取消某个宏的定义,否则该宏将在定义后的所有位置有定义,而且会覆盖函数名和变量名。所以使用宏时要特别小心,一般会严格遵循特定的命名规则以防止和其他变量或宏发生冲突。
#error 错误 信息
可以让预编译器产生错误停止编译
#warning 警告 信息
可以让预编译器产生警告
int/*评论*/x;
相当于 int x;
。
__cplusplus
用于判断是否在使用 C++(而不是 C),以及判断使用的 C++ 标准,例如 #if __cplusplus >= 201103L
(L
表示这是一个 long
的 literal)
__FILE__
会替换为当前的文件名(一个字符串 literal)。
__LINE__
会替换为当前的行号(一个 int
的 literal)。
__DATE__
"Mmm dd yyyy" (e.g., "Apr 18 2023")
__TIME__
"hh:mm:ss"
__func__
是当前函数名,但这并不是一个宏,而是每个函数都会在开始默认定义的一个 const char[]
,存有当前函数名。
FUN(参数) #参数
在参数两边加双引号。
#define FOO(x) BAR(x)
,#define BAR(x) #x
。那么 BAR(1+1)
就是 "1+1"
,但是 FOO(1+1)
就是 "2"
。
#宏
只能用于宏参数前面,用于其他宏名,更不能直接在宏定义外面用。一个常用的宏函数是 #define STRINGIFY(x) #x
#include <iostream>
using namespace std;
#define ITEM wi383uk33 "abcde
#define STRINGIFY(x) #x
#define STRINGIFY2(x) STRINGIFY(x)
int main()
{
cout << STRINGIFY(ITEM) << endl; // "ITEM"
cout << STRINGIFY2(ITEM) << endl; // R"(ITEM wi383uk33 "abcde)"
}
##
可以用于拼接代码(两边可以有或没有空格)例如 #define MY_VAR(x) ab ## x ## cde
。调用 MY_VAR(2)
展开为 ab2cde
。