162 lines
16 KiB
HTML
162 lines
16 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-c_language_translation_phases 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="c.html">c</a>‎ | <a href="c-language.html">language</a></span></div>
|
|
<div id="mw-content-text" lang="zh" dir="ltr" class="mw-content-ltr" xml:lang="zh">
|
|
<p>编译器<i>如同</i>下列阶段以此准确顺序发生一般处理 C 源文件。实际实现可以组合,或以不同方式处理这些动作,只要行为相同。</p>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_1">阶段 1</span></h3>
|
|
<div class="t-li1"><span class="t-li">1)</span> 以实现定义方式,映射源文件(通常是以某种多字节,例如 UTF-8 编码的文本文件)的单独字节,为<i>源字符集</i>的字符。特别是以换行字符替换依赖 OS 的行尾指示符。
|
|
<dl>
|
|
<dd><i>源字符集</i>是包含作为单字节子集的<i>基本源字符集</i>的多字节字符集,后者由以下 96 个字符组成:</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="t-li2"><span class="t-li">a)</span> 5 个空白字符(空格、水平制表、垂直制表、换页、换行)</div>
|
|
<div class="t-li2"><span class="t-li">b)</span> 10 个数字字符,从 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">'0'</span></span></span> 到 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">'9'</span></span></span></div>
|
|
<div class="t-li2"><span class="t-li">c)</span> 52 个字母,从 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">'A'</span></span></span> 到 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">'Z'</span></span></span> 以及从 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">'a'</span></span></span> 到 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">'z'</span></span></span></div>
|
|
<div class="t-li2"><span class="t-li">d)</span> 29 个标点字符: <span class="t-c"><span class="mw-geshi c source-c">_ <span class="br0">{</span> <span class="br0">}</span> <span class="br0">[</span> <span class="br0">]</span> <span class="co2"># ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '</span></span></span></div>
|
|
<div class="t-li1"><span class="t-li">2)</span> 以对应的单字节表示替换<a href="c-language-operator_alternative.html">三标符</a>。</div>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_2">阶段 2</span></h3>
|
|
<div class="t-li1"><span class="t-li">1)</span> 凡在反斜杠出现于行尾(立即为换行符所后随)时,删除反斜杠和换行符,把二个物理源码行组合成一个逻辑源码行。这是单趟操作:以二个反斜杠结束,后随一个空行的行不会把三行组合为一。</div>
|
|
<div class="t-li1"><span class="t-li">2)</span> 若此步骤后,非空源文件不以换行符结束(无论是原本就无换行,还是以反斜杠结束),则行为未定义。</div>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_3">阶段 3</span></h3>
|
|
<div class="t-li1"><span class="t-li">1)</span> 将源文件分解为<a href="c-comment.html">注释</a>、空白字符(空格、水平制表、换行、垂直制表、换页)序列和下列<i>预处理记号</i>:</div>
|
|
<div class="t-li2"><span class="t-li">a)</span> 头文件名: <span class="t-c"><span class="mw-geshi c source-c"><span class="sy1"><</span>stdio.<span class="me1">h</span><span class="sy1">></span></span></span> 或 <span class="t-c"><span class="mw-geshi c source-c"><span class="st0">"myfile.h"</span></span></span></div>
|
|
<div class="t-li2"><span class="t-li">b)</span> <a href="c-language-identifier.html">标识符</a></div>
|
|
<div class="t-li2"><span class="t-li">c)</span> 预处理数字,包括<a href="c-language-integer_constant.html">整数常量</a>和<a href="c-language-floating_constant.html">浮点常量</a>,但也包括一些非法记号,例如 <span class="t-c"><span class="mw-geshi c source-c"><span class="nu0">1</span>..<span class="me1">E</span><span class="sy2">+</span>3.<span class="me1">foo</span></span></span> 或 <span class="t-c"><span class="mw-geshi c source-c">0JBK</span></span></div>
|
|
<div class="t-li2"><span class="t-li">d)</span> <a href="c-language-character_constant.html">字符常量</a>与<a href="c-language-string_literal.html">字符串字面量</a></div>
|
|
<div class="t-li2"><span class="t-li">e)</span> 运算符与标点,例如 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy2">+</span></span></span> 、 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy1"><<=</span></span></span> 、 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy1"><</span><span class="sy2">%</span></span></span> 或 <span class="t-c"><span class="mw-geshi c source-c"><span class="co2">##</span></span></span> 。</div>
|
|
<div class="t-li2"><span class="t-li">f)</span> 不属于任何其他类别的单独非空白字符</div>
|
|
<div class="t-li1"><span class="t-li">2)</span> 以一个空格字符替换每段注释</div>
|
|
<div class="t-li1"><span class="t-li">3)</span> 保持换行符。是否可将非换行的空白符序列缩减成单个空格字符是实现定义的。</div>
|
|
<p><span id=".E6.9C.80.E5.A4.A7.E5.90.9E.E5.99.AC"></span> 若已经分析输入为到给定字符为止的预处理记号,则通常将能构成一个预处理记号的最长字符序列处理成下个预处理记号,即这会导致后继分析失败。这常被称为<i>最大吞噬 (maximal munch)</i> 。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">int</span> foo <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> bar <span class="sy1">=</span> <span class="nu12">0xE</span><span class="sy2">+</span>foo<span class="sy4">;</span> <span class="co1">// 错误:非法的预处理数字 0xE+foo</span>
|
|
<span class="kw4">int</span> baz <span class="sy1">=</span> <span class="nu12">0xE</span> <span class="sy2">+</span> foo<span class="sy4">;</span> <span class="co1">// OK</span>
|
|
|
|
<span class="kw4">int</span> quux <span class="sy1">=</span> bar<span class="sy2">+++++</span>baz<span class="sy4">;</span> <span class="co1">// 错误: bar++ ++ +baz ,而非 bar++ + ++baz 。</span></pre></div>
|
|
</div>
|
|
<p>最大吞噬规则的单独例外是:</p>
|
|
<ul>
|
|
<li>头文件名预处理记号仅在 <code>#include</code> 指令中和 <code>#pragma</code> 指令中的实现定义位置形成。</li>
|
|
</ul>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="co2">#define MACRO_1 1</span>
|
|
<span class="co2">#define MACRO_2 2</span>
|
|
<span class="co2">#define MACRO_3 3</span>
|
|
<span class="co2">#define MACRO_EXPR (MACRO_1 <MACRO_2> MACRO_3) // OK : <MACRO_2> 不是头文件名</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_4">阶段 4</span></h3>
|
|
<div class="t-li1"><span class="t-li">1)</span> 执行<a href="c-preprocessor.html">预处理器</a>。</div>
|
|
<div class="t-li1"><span class="t-li">2)</span> <a href="c-preprocessor-include.html">#include</a> 指令所引入的每个文件都经历阶段 1 到 4 ,递归执行。</div>
|
|
<div class="t-li1"><span class="t-li">3)</span> 此阶段结束时,从源码移除所有预处理器指令。</div>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_5">阶段 5</span></h3>
|
|
<div class="t-li1"><span class="t-li">1)</span> 将<a href="c-language-character_constant.html">字符常量</a>及<a href="c-language-string_literal.html">字符串字面量</a>中的所有字符及<a href="c-language-escape.html">转义序列</a>从<i>源字符集</i>转换成<i>执行字符集</i>(可为如 UTF-8 的多字节字符集,只要来自阶段 1 中所列的<i>基本源字符集</i>的所有 96 个字符拥有单字节表示)。若转义序列所指定的字符不是执行字符集的成员,则结果是实现定义的,但保证不是空(宽)字符。</div>
|
|
<p>注意:某些实现中,能以命令行选项控制此阶段所进行的转换: gcc 和 clang 用 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy2">-</span>finput<span class="sy2">-</span>charset</span></span> 指定源字符集的编码,用 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy2">-</span>fexec<span class="sy2">-</span>charset</span></span> 和 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy2">-</span>fwide<span class="sy2">-</span>exec<span class="sy2">-</span>charset</span></span> 指定<span class="t-rev-inl t-since-c11"><span>无编码前缀的</span> <span><span class="t-mark-rev t-since-c11">(C11 起)</span></span></span>字符串字面量和字符常量中的执行字符集的编码。</p>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_6">阶段 6</span></h3>
|
|
<p>连接相邻的<a href="c-language-string_literal.html">字符串字面量</a>。</p>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_7">阶段 7</span></h3>
|
|
<p>发生编译:按照语法和语义分析记号,并将它们翻译成翻译单元。</p>
|
|
<h3><span class="mw-headline" id=".E9.98.B6.E6.AE.B5_8">阶段 8</span></h3>
|
|
<p>发生链接:将翻译单元和满足外部引用所需的库组件到汇集成程序映像,它含有在其执行环境(操作系统)中执行所需的信息。</p>
|
|
<h3><span class="mw-headline" id=".E5.BC.95.E7.94.A8">引用</span></h3>
|
|
<div class="t-ref-std-11">
|
|
<ul>
|
|
<li>C11 标准(ISO/IEC 9899:2011):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.1.1.2 Translation phases (p: 10-11)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.2.1 Character sets (p: 22-24)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.4 Lexical elements (p: 57-75)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<div class="t-ref-std-c99">
|
|
<ul>
|
|
<li>C99 标准(ISO/IEC 9899:1999):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.1.1.2 Translation phases (p: 9-10)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>5.2.1 Character sets (p: 17-19)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.4 Lexical elements (p: 49-66)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<div class="t-ref-std-c89">
|
|
<ul>
|
|
<li>C89/C90 标准(ISO/IEC 9899:1990):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>2.1.1.2 Translation phases</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>2.2.1 Character sets</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>3.1 Lexical elements</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E5.8F.82.E9.98.85">参阅</span></h3>
|
|
<table class="t-dsc-begin"></table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|