358 lines
36 KiB
HTML
358 lines
36 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh" dir="ltr" class="client-nojs" xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh">
|
|
<head><meta http-equiv="x-ua-compatible" content="ie=edge">
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
<title>文本替换宏</title>
|
|
<link rel="stylesheet" href="ext.css" />
|
|
<link rel="stylesheet" href="site_modules.css" />
|
|
</head>
|
|
<body class="mediawiki ltr sitedir-ltr ns-0 ns-subject page-cpp_preprocessor_replace skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">文本替换宏</h1>
|
|
<div id="bodyContent">
|
|
<div id="contentSub"><span class="subpages">< <a href="cpp.html">cpp</a>‎ | <a href="cpp-preprocessor.html">preprocessor</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>预处理器支持文本宏替换和仿函数文本宏替换。</p>
|
|
<h3><span class="mw-headline" id=".E8.AF.AD.E6.B3.95">语法</span></h3>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>#define</b></code> <span class="t-spar">标识符</span> <span class="t-spar">替换列表</span><span class="t-mark">(可选)</span></td>
|
|
<td>(1)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>#define</b></code> <span class="t-spar">标识符</span><code><b>(</b></code> <span class="t-spar">形参</span> <code><b>)</b></code> <span class="t-spar">替换列表</span><span class="t-mark">(可选)</span></td>
|
|
<td>(2)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>#define</b></code> <span class="t-spar">标识符</span><code><b>(</b></code> <span class="t-spar">形参</span><code><b>, ... )</b></code> <span class="t-spar">替换列表</span><span class="t-mark">(可选)</span></td>
|
|
<td>(3)</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>#define</b></code> <span class="t-spar">标识符</span><code><b>( ... )</b></code> <span class="t-spar">替换列表</span><span class="t-mark">(可选)</span></td>
|
|
<td>(4)</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td><code><b>#undef</b></code> <span class="t-spar">标识符</span></td>
|
|
<td>(5)</td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<h4><span class="mw-headline" id=".23define_.E6.8C.87.E4.BB.A4"><code>#define</code> 指令</span></h4>
|
|
<p><code>#define</code> 指令将 <span class="t-spar">标识符</span> 定义为宏,即指示编译器以将其后出现的所有 <span class="t-spar">标识符</span> 都替换为 <span class="t-spar">替换列表</span>,而它也可以被进一步处理。如果该标识符已被定义为任何类型的宏,那么除非这些定义都相同,否则程序非良构。</p>
|
|
<h5><span class="mw-headline" id=".E4.BB.BF.E5.AF.B9.E8.B1.A1.E5.AE.8F">仿对象宏</span></h5>
|
|
<p>仿对象宏(object-like)以 <span class="t-spar">替换列表</span> 替换每次出现的被定义 <span class="t-spar">标识符</span>。<code>#define</code> 指令的版本 (1) 准确表现如此。</p>
|
|
<h5><span class="mw-headline" id=".E4.BB.BF.E5.87.BD.E6.95.B0.E5.AE.8F">仿函数宏</span></h5>
|
|
<p>仿函数宏(function-like)以 <span class="t-spar">替换列表</span> 替换每次出现的被定义 <span class="t-spar">标识符</span>,可选地接受一定量的实参,它们随即替换掉 <span class="t-spar">替换列表</span> 中出现的任何对应的 <span class="t-spar">形参</span>。</p>
|
|
<p>仿函数宏语法类似函数调用语法:每个宏名实例后随一个 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="br0">(</span></span></span> 作为下个预处理记号,所引入的记号序列将被替换为 <span class="t-spar">替换列表</span>。该序列以匹配的 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="br0">)</span></span></span> 记号终止,跳过中间的匹配左右括号对。</p>
|
|
<p>对于版本 (2),实参数量必须与宏定义中的形参数量相同。对于版本 (3,4) ,实参数量必须<span class="t-rev-inl t-until-cxx20"><span>多于</span> <span><span class="t-mark-rev t-until-cxx20">(C++20 前)</span></span></span><span class="t-rev-inl t-since-cxx20"><span>不少于</span> <span><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></span></span>形参数量(不计 <code><b>...</b></code>)。否则程序非良构。如果标识符未使用函数写法,即它自身之后没有括号,那么它完全不被替换。</p>
|
|
<p><code>#define</code> 指令的版本 (2) 定义简单仿函数宏。</p>
|
|
<p><code>#define</code> 指令的版本 (3) 定义有可变数量实参的仿函数宏。额外的实参(是谓<i>可变实参</i>)可用 <code>__VA_ARGS__</code> 标识符访问,它会被与要被替换的标识符一起提供的实参替换。</p>
|
|
<p><code>#define</code> 指令的版本 (4) 定义有可变数量实参的仿函数宏,但无常规实参。额外的实参(是谓<i>可变实参</i>)只能用 <code>__VA_ARGS__</code> 标识符访问,它会被与要被替换的标识符一起提供的实参替换。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<p>对于版本 (3,4),<span class="t-spar">替换列表</span> 可以含有记号序列“<code><b>__VA_OPT__ (</b></code> <span class="t-spar">内容</span> <code><b>)</b></code>”,如果 <code>__VA_ARGS__</code> 非空,那么它会被 <span class="t-spar">内容</span> 替换,否则不展开成任何内容。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)</span>
|
|
<span class="co2">#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)</span>
|
|
<span class="co2">#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })</span>
|
|
F<span class="br0">(</span>a, b, c<span class="br0">)</span> <span class="co1">// 替换为 f(0, a, b, c)</span>
|
|
F<span class="br0">(</span><span class="br0">)</span> <span class="co1">// 替换为 f(0)</span>
|
|
G<span class="br0">(</span>a, b, c<span class="br0">)</span> <span class="co1">// 替换为 f(0, a, b, c)</span>
|
|
G<span class="br0">(</span>a, <span class="br0">)</span> <span class="co1">// 替换为 f(0, a)</span>
|
|
G<span class="br0">(</span>a<span class="br0">)</span> <span class="co1">// 替换为 f(0, a)</span>
|
|
SDEF<span class="br0">(</span>foo<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 替换为 S foo;</span>
|
|
SDEF<span class="br0">(</span>bar, <span class="nu0">1</span>, <span class="nu0">2</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 替换为 S bar = { 1, 2 };</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>注意:如果仿函数宏的实参中包含不为匹配的左右括号对所保护的逗号(最常出现于模板实参列表中,如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-error-assert.html"><span class="kw774">assert</span></a><span class="br0">(</span><a href="cpp-types-is_same.html"><span class="kw589">std::<span class="me2">is_same_v</span></span></a><span class="sy1"><</span><span class="kw4">int</span>, <span class="kw4">int</span><span class="sy1">></span><span class="br0">)</span><span class="sy4">;</span></span></span> 或 <span class="t-c"><span class="mw-geshi cpp source-cpp">BOOST_FOREACH<span class="br0">(</span><a href="cpp-utility-pair.html"><span class="kw1096">std::<span class="me2">pair</span></span></a><span class="sy1"><</span><span class="kw4">int</span>,<span class="kw4">int</span><span class="sy1">></span> p, m<span class="br0">)</span></span></span>),那么逗号被解释成宏实参分隔符,并造成由于实参数量不匹配所致的编译失败。</p>
|
|
<h4><span class="mw-headline" id=".E4.BF.9D.E7.95.99.E5.AE.8F.E5.90.8D">保留宏名</span></h4>
|
|
<p>包含标准库头文件的翻译单元不可 <code>#define</code> 或 <code>#undef</code> 声明于任何标准库头文件中所声明的名字。</p>
|
|
<p>使用标准库任何部分的翻译单元不可 <code>#define</code> 或 <code>#undef</code> 词法上等同于下列内容的名称:</p>
|
|
<ul>
|
|
<li><a href="cpp-keyword.html">关键字</a></li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<ul>
|
|
<li><a href="cpp-keyword.html">有特殊含义的标识符</a></li>
|
|
<li><a href="cpp-language-attributes.html#.E6.A0.87.E5.87.86.E5.B1.9E.E6.80.A7">任何标准属性记号</a></li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<p>除了可定义 <code>likely</code> 与 <code>unlikely</code> 为仿函数宏。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>否则,行为未定义。</p>
|
|
<h4><span class="mw-headline" id=".23_.E4.B8.8E_.23.23_.E8.BF.90.E7.AE.97.E7.AC.A6"><code>#</code> 与 <code>##</code> 运算符</span></h4>
|
|
<p>仿函数宏中,如果<span class="t-spar">替换列表</span> 中一个标识符前有 <code>#</code> 运算符,那么该标识符在运行形参替换的基础上以引号包围,实际上创建一个字符串字面量。另外,预处理器为内嵌的字符串字面量(如果存在)外围的引号添加反斜杠以进行转义,并按需要双写字符串中的反斜杠。移除所有前导和尾随空白符,并将文本中间(除内嵌字符串字面量中间外)的任何空白符序列缩减成单个空格。此操作被称为“字符串化”,如果字符串化的结果不是合法的字符串字面量,那么行为未定义。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<p><code>#</code> 出现于 <code>__VA_ARGS__</code> 之前时,展开后的 __VA_ARGS__ 整体被包在引号中:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#define showlist(...) puts(#__VA_ARGS__)</span>
|
|
showlist<span class="br0">(</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 展开成 puts("")</span>
|
|
showlist<span class="br0">(</span><span class="nu0">1</span>, <span class="st0">"x"</span>, <span class="kw4">int</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 展开成 puts("1, \"x\", int")</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>如果 <span class="t-spar">替换列表</span> 中任何两个相继标识符之间有 <code>##</code> 运算符,那么这两个标识符(首先未被宏展开)在运行形参替换的基础上将结果进行拼接。此操作被称为“拼接”或“记号粘贴”。只有一同组成合法记号的记号才可以粘贴:如组成更长标识符的标识符、组成数字的数字位,或组成 <code>+=</code> 的运算符 <code>+</code> 和 <code>=</code>。不能通过粘贴 <code>/</code> 和 <code>*</code> 来创建注释,这是因为注释在考虑文本宏替换前就已经被移除了。<span class="t-rev-inl t-since-cxx23"><span>如果结果以一个与<a href="cpp-language-escape.html">通用字符名</a>的语法匹配的序列起始,那么行为未定义。在<a href="cpp-language-translation_phases.html#.E9.98.B6.E6.AE.B5_3">翻译阶段 3</a>中的通用字符名替换不算在内。</span> <span><span class="t-mark-rev t-since-cxx23">(C++23 起)</span></span></span>如果连接的结果不是合法记号,那么行为未定义。</p>
|
|
<p>注意:一些编译器提供了一项扩展,允许 ## 出现于逗号后及 __VA_ARGS__ 前,此情况下 ## 在存在可变实参时不做任何事,但在不存在可变实参时移除逗号:这使得可以定义如 <code>fprintf (stderr, format, ##__VA_ARGS__)</code> 这样的宏。</p>
|
|
<h4><span class="mw-headline" id=".23undef_.E6.8C.87.E4.BB.A4"><code>#undef</code> 指令</span></h4>
|
|
<p><code>#undef</code> 指令取消定义 <span class="t-spar">标识符</span>,即取消 <code>#define</code> 指令所作的 <span class="t-spar">标识符</span> 定义。如果标识符未关联到宏,那么忽略该指令。</p>
|
|
<h3><span class="mw-headline" id=".E9.A2.84.E5.AE.9A.E4.B9.89.E5.AE.8F">预定义宏</span></h3>
|
|
<p>下列宏名已预定义于每个翻译单元中。</p>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__cplusplus</span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>代表所用的 C++ 标准版本,展开成值
|
|
<ul>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">199711L</span></span></span><span class="t-mark-rev t-until-cxx11">(C++11 前)</span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">201103L</span></span></span><span class="t-mark-rev t-since-cxx11">(C++11)</span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">201402L</span></span></span><span class="t-mark-rev t-since-cxx14">(C++14)</span></li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">201703L</span></span></span><span class="t-mark-rev t-since-cxx17">(C++17)</span>,或</li>
|
|
<li><span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">202002L</span></span></span><span class="t-mark-rev t-since-cxx20">(C++20)</span><br />
|
|
<span class="t-mark">(宏常量)</span></li>
|
|
</ul>
|
|
</td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDC_HOSTED__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果实现有宿主(在操作系统下运行)则展开成整数常量 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">1</span></span></span>,如果实现自立(不在操作系统下运行)则展开成 <span class="t-c"><span class="mw-geshi cpp source-cpp">​<span class="nu0">0</span>​</span></span><br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__FILE__</span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>展开成当前文件名,作为字符串字面量,可用 <a href="cpp-preprocessor-line.html"><code>#line</code></a> 指令更改<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__LINE__</span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>展开成源文件行号,整数常量,可用 <a href="cpp-preprocessor-line.html"><code>#line</code></a> 指令更改<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__DATE__</span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>展开成翻译日期,形式为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="st0">"Mmm dd yyyy"</span></span></span> 的字符串。如果月中日期数小于 10 则 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="st0">"dd"</span></span></span> 的首字符为空格。月份名如同以 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-chrono-c-asctime.html"><span class="kw1015">std::<span class="me2">asctime</span></span></a><span class="br0">(</span><span class="br0">)</span></span></span> 生成<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__TIME__</span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>展开成翻译时间,形式为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="st0">"hh:mm:ss"</span></span></span> 的字符串字面量<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDCPP_DEFAULT_NEW_ALIGNMENT__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx17">(C++17)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>展开成 <span class="t-lc"><a href="cpp-types-size_t.html">std::size_t</a></span> 字面量,其值为对不具对齐的 <span class="t-lc"><a href="cpp-memory-new-operator_new.html">operator new</a></span> 的调用所保证的对齐(更大的对齐将传递给具对齐重载,如 <span class="t-c"><span class="mw-geshi cpp source-cpp"><a href="cpp-memory-new-operator_new.html"><span class="kw687">operator new</span></a><span class="br0">(</span><a href="cpp-types-size_t.html"><span class="kw100">std::<span class="me2">size_t</span></span></a>, <a href="cpp-memory-new-align_val_t.html"><span class="kw697">std::<span class="me2">align_val_t</span></span></a><span class="br0">)</span></span></span>)<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>实现可能预定义下列其他的宏名。</p>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDC__</span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果存在则为实现定义值,典型地用于指示 C 遵从性<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDC_VERSION__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果存在则为实现定义值<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDC_ISO_10646__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">wchar_t</span></span></span> 使用 Unicode ,则展开成 <span class="t-c"><span class="mw-geshi cpp source-cpp">yyyymmL</span></span> 形式的整数常量,日期指示所支持的 Unicode 的最近版本<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDC_MB_MIGHT_NEQ_WC__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果对于基本字符集成员 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="st0">'x'</span> <span class="sy1">==</span> L<span class="st0">'x'</span></span></span> 可能为假,则展开成 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">1</span></span></span>,如在基于 EBCDIC 并且为 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="kw4">wchar_t</span></span></span> 使用 Unicode 的系统上。<br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDCPP_THREADS__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果程序能拥有多于一个执行线程则展开成 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">1</span></span></span><br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-dsc-begin">
|
|
<tr class="t-dsc">
|
|
<td>
|
|
<div class="t-dsc-member-div">
|
|
<div><span class="t-lines"><span>__STDCPP_STRICT_POINTER_SAFETY__</span></span></div>
|
|
<div><span class="t-lines"><span><span class="t-mark-rev t-since-cxx11">(C++11)</span><span class="t-mark-rev t-until-cxx23">(C++23 中移除)</span></span></span></div>
|
|
</div>
|
|
</td>
|
|
<td>如果实现支持严格 <span class="t-lc"><a href="cpp-memory-gc-pointer_safety.html">std::pointer_safety</a></span> 则展开成 <span class="t-c"><span class="mw-geshi cpp source-cpp"><span class="nu0">1</span></span></span><br />
|
|
<span class="t-mark">(宏常量)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>这些宏的值(除了 <code>__FILE__</code> 和 <code>__LINE__</code>)在整个翻译单元保持为常量。试图重定义或取消定义这些宏会导致未定义行为。</p>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx11">
|
|
<td>
|
|
<p>注意:在每个函数体的作用域内部都有一个名为 <span class="t-c"><span class="mw-geshi cpp source-cpp">__func__</span></span> 的特殊的函数局域预定义变量,它被定义为一个持有具有实现定义格式的函数名的静态字符数组。它不是预处理器宏,但它与 <code>__FILE__</code> 和 <code>__LINE__</code> 一起使用,例如 <span class="t-lc"><a href="cpp-error-assert.html">assert</a></span>。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx11">(C++11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-cxx20">
|
|
<td>
|
|
<h4><span class="mw-headline" id=".E8.AF.AD.E8.A8.80.E5.8A.9F.E8.83.BD.E7.89.B9.E6.80.A7.E6.B5.8B.E8.AF.95.E5.AE.8F">语言功能特性测试宏</span></h4>
|
|
<p>标准定义一组对应于 C++11 或之后引入的 C++ 语言功能特性的预处理器宏。它们被用来以简单且可移植的方式检测所说的特性是否存在。</p>
|
|
<p>详见<a href="cpp-feature_test.html">功能特性测试</a> 。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-cxx20">(C++20 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E7.A4.BA.E4.BE.8B">示例</span></h3>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="cpp source-cpp">
|
|
<pre class="de1"><span class="co2">#include <iostream></span>
|
|
|
|
<span class="co1">// 制造函数工厂并使用它</span>
|
|
<span class="co2">#define FUNCTION(name, a) int fun_##name() { return a;}</span>
|
|
|
|
FUNCTION<span class="br0">(</span>abcd, <span class="nu0">12</span><span class="br0">)</span>
|
|
FUNCTION<span class="br0">(</span>fff, <span class="nu0">2</span><span class="br0">)</span>
|
|
FUNCTION<span class="br0">(</span>qqq, <span class="nu0">23</span><span class="br0">)</span>
|
|
|
|
<span class="co2">#undef FUNCTION</span>
|
|
<span class="co2">#define FUNCTION 34</span>
|
|
<span class="co2">#define OUTPUT(a) std::cout << "output: " #a << '\n'</span>
|
|
|
|
<span class="co1">// 在后面的宏定义中使用之前的宏</span>
|
|
<span class="co2">#define WORD "Hello "</span>
|
|
<span class="co2">#define OUTER(...) WORD #__VA_ARGS__</span>
|
|
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"abcd: "</span> <span class="sy1"><<</span> fun_abcd<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"fff: "</span> <span class="sy1"><<</span> fun_fff<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> <span class="st0">"qqq: "</span> <span class="sy1"><<</span> fun_qqq<span class="br0">(</span><span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> FUNCTION <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
OUTPUT<span class="br0">(</span>million<span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 注意这里没有引号</span>
|
|
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> OUTER<span class="br0">(</span>World<span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<a href="cpp-io-cout.html"><span class="kw1758">std::<span class="me2">cout</span></span></a> <span class="sy1"><<</span> OUTER<span class="br0">(</span>WORD World<span class="br0">)</span> <span class="sy1"><<</span> <span class="st0">'<span class="es1">\n</span>'</span><span class="sy4">;</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>输出:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="text source-text">
|
|
<pre class="de1">abcd: 12
|
|
fff: 2
|
|
qqq: 23
|
|
34
|
|
output: million
|
|
Hello World
|
|
Hello WORD World</pre></div>
|
|
</div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<table class="t-dsc-begin"></table>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|