贡献者: 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。
#define OP_FUNCTIONS(XX) \
XX(my_func1) \
XX(my_func2) \
XX(my_func3) \
#define XX(name) void *name();
OP_FUNCTIONS(XX)
#undef XX
void print_funcs()
{
#define XX(name) printf(#name "\n");
OP_FUNCTIONS(XX)
#undef XX
}
void call_funcs()
{
#define XX(name) name();
OP_FUNCTIONS(XX)
#undef XX
}
会展开为
void *my_func1();
void *my_func2();
void *my_func3();
void print_funcs()
{
printf("my_func1\n");
printf("my_func2\n");
printf("my_func3\n");
}
void call_funcs()
{
my_func1();
my_func2();
my_func3();
}