在线文档教程
C++
语言 | Language

#define directive

替换文本宏

预处理器支持文本宏替换。还支持类似函数的文本宏替换。

句法

#define identifier replacement-list(optional)(1)
#define identifier( parameters ) replacement-list(2)
#define identifier( parameters, ... ) replacement-list(3)(since C++11)
#define identifier( ... ) replacement-list(4)(since C++11)
#undef identifier(5)

解释

#define指令

#define指令将标识符定义为宏,即指示编译器用替换列表替换所有连续出现的标识符,这些标识符可以另外处理。如果标识符已经定义为任何类型的宏,则程序的格式不正确,除非定义相同。

类对象宏

类似对象的宏用替换列表替换每个出现的已定义标识符。版本%281%29#define指令的行为就是这样。

类功能宏

类似于函数的宏用替换列表替换每个已定义标识符的出现,另外,使用一些参数,这些参数然后替换替换列表中任何参数的相应出现。

类似于函数的宏调用的语法类似于函数调用的语法:宏名称的每个实例后面跟着一个(作为下一次预处理,令牌引入了由替换列表替换的令牌序列。通过匹配终止序列。)标记,跳过中间匹配的左括号和右括号对。

参数的数量必须与宏定义中的参数数%28参数%29相同,否则程序的格式不正确。如果标识符不是用函数表示法表示的,即它本身之后没有括号,则它根本不被替换。

版本%282%29#define指令定义一个简单的类似函数的宏。

版本%283%29#define指令定义了一个具有可变参数数的类似函数的宏。可以使用__VA_ARGS__标识符,然后用参数替换,并提供要替换的标识符。

版本%284%29#define指令定义了一个类似函数的宏,它有可变的参数数,但没有常规的参数.。只能在以下情况下访问这些参数:__VA_ARGS__标识符,然后用参数替换,并提供要替换的标识符。

注意:如果类似于函数的宏的参数包含不受匹配的左括号和右括号保护的逗号,则%28最常见于类型名称中,如assert(std::is_same_v<int, int>或BOOST_FOREACH(std::pair<int,int> p, m)%29,逗号被解释为宏参数分隔符,由于参数计数不匹配导致编译失败。

#和##操作者

在类似功能的宏中,#运算符在替换列表中的标识符之前,通过参数替换运行标识符,并将结果以引号括起来,从而有效地创建字符串文本。此外,预处理器还添加反斜杠以转义嵌入字符串文本(如果有的话)周围的引号,并根据需要将字符串中的反斜杠加倍。所有前导和尾随空格都将被删除,文本中间的任何空格序列(但不在嵌入式字符串文本%29中)都会折叠为单个空格。这个操作叫做“串”。如果字符串化的结果不是有效的字符串文字,则行为是未定义的。

When # appears before __VA_ARGS__, the entire expanded __VA_ARGS__ is enclosed in quotes: #define showlist(...) puts(#__VA_ARGS__) showlist( // expands to puts("") showlist(1, "x", int // expands to puts("1, \"x\", int")(since C++11)

##替换列表中的任意两个连续标识符之间的运算符对两个标识符%28运行参数替换,这两个标识符不是宏展开的,首先是%29,然后连接结果。此操作称为“级联”或“令牌粘贴”。只能粘贴在一起构成有效令牌的令牌:形成较长标识符的标识符、构成数字的数字或运算符。+=形成一个+=.无法通过粘贴创建注释/*因为在考虑宏替换之前,注释会从文本中删除。如果级联的结果不是有效的令牌,则行为是未定义的。

注意:一些编译器提供了一个扩展,允许##出现在逗号后面和前面[医][医]Va[医]阿格斯[医][医],在这种情况下##什么也不做[医][医]Va[医]阿格斯[医][医]为非空,但在[医][医]Va[医]阿格斯[医][医]为空:这使定义宏成为可能,例如fprintf (stderr, format, ##__VA_ARGS__)...

#undef指令

#undef指令取消标识符的定义,即取消先前的标识符定义。#define指令。如果标识符没有关联宏,则忽略指令。

预定义宏

在任何翻译单元中都预定义了以下宏名称。

__cplusplusdenotes the version of C++ standard that is being used, expands to value 199711L(until C++11), 201103L(C++11), 201402L(C++14), or 201703L(C++17) (macro constant)
__STDC_HOSTED__ (C++11)expands to the integer constant 1 if the implementation is hosted (runs under an OS), ​0​ if freestanding (runs without an OS) (macro constant)
__FILE__expands to the name of the current file, as a character string literal, can be changed by the #line directive (macro constant)
__LINE__expands to the source file line number, an integer constant, can be changed by the #line directive (macro constant)
__DATE__expands to the date of translation, a character string literal of the form "Mmm dd yyyy". The first character of "dd" is a space if the day of the month is less than 10. The name of the month is as if generated by std::asctime() (macro constant)
__TIME__expands to the time of translation, a character string literal of the form "hh:mm:ss" (macro constant)
__STDCPP_DEFAULT_NEW_ALIGNMENT__ (C++17)expands to an std::size_t literal whose value is the alignment guaranteed by a call to alignment-unaware operator new (larger alignments will be passed to alignment-aware overload, such as operator new(std::size_t, std::align_val_t) (macro constant)

实现可以预定义下列其他宏名称。

__STDC__implementation-defined value, if present, typically used to indicate C conformance (macro constant)
__STDC_VERSION__ (C++11)implementation-defined value, if present (macro constant)
__STDC_ISO_10646__ (C++11)expands to an integer constant of the form yyyymmL, if wchar_t uses Unicode, the date indicates the latest revision of Unicode supported (macro constant)
__STDC_MB_MIGHT_NEQ_WC__ (C++11)expands to 1 if wide character encoding of the basic character set may not equal their narrow encoding (macro constant)
__STDCPP_STRICT_POINTER_SAFETY__ (C++11)expands to 1 if the implementation has strict std::pointer_safety (macro constant)
__STDCPP_THREADS__ (C++11)expands to 1 if the program can have more than one thread of execution (macro constant)

这些宏的值为%28,但__FILE____LINE__%29在整个翻译单位保持不变。试图重新定义或取消定义这些宏会导致未定义的行为。

注意:在每个函数体的范围内,都有一个特殊的函数--局部预定义变量,名为__func__%28自C++11%29以来,定义为一个静态字符数组,以实现定义格式保存函数的名称。它不是预处理器宏,但它与__FILE____LINE__,例如assert...

二次

#include <iostream> //make function factory and use it #define FUNCTION(name, a) int fun_##name() { return a;} FUNCTION(abcd, 12) FUNCTION(fff, 2) FUNCTION(qqq, 23) #undef FUNCTION #define FUNCTION 34 #define OUTPUT(a) std::cout << #a << '\n' int main() { std::cout << "abcd: " << fun_abcd() << '\n'; std::cout << "fff: " << fun_fff() << '\n'; std::cout << "qqq: " << fun_qqq() << '\n'; std::cout << FUNCTION << '\n'; OUTPUT(million //note the lack of quotes }

二次

产出:

二次

abcd: 12 fff: 2 qqq: 23 34 million

二次

另见

用于替换文本宏的文档

*。

© cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

http://en.cppreference.com/w/cpp/preProcessor/置换