129 lines
15 KiB
HTML
129 lines
15 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_extern 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>在<a href="c-language-translation_phases.html">翻译单元</a>的顶层(及在预处理器后拥有所有 #include 的源文件),每个 C 程序都是<a href="c-language-declarations.html">声明</a>的序列,它们声明函数和拥有<a href="c-language-storage_duration.html">外部链接</a>的对象。这些声明被称作<i>外部声明</i>,因为它们出现于任何函数的外部。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw2">extern</span> <span class="kw4">int</span> n<span class="sy4">;</span> <span class="co1">// 外部声明拥有外部链接</span>
|
|
<span class="kw4">int</span> b <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 外部定义拥有外部链接</span>
|
|
<span class="kw4">static</span> <span class="kw4">const</span> <span class="kw4">char</span> <span class="sy2">*</span>c <span class="sy1">=</span> <span class="st0">"abc"</span><span class="sy4">;</span> <span class="co1">// 外部定义拥有内部链接</span>
|
|
<span class="kw4">int</span> f<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span> <span class="br0">{</span> <span class="co1">// 外部定义拥有外部链接</span>
|
|
<span class="kw4">int</span> a <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 非外部</span>
|
|
<span class="kw1">return</span> b<span class="sy4">;</span>
|
|
<span class="br0">}</span>
|
|
<span class="kw4">static</span> <span class="kw4">void</span> x<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span> <span class="br0">{</span> <span class="co1">// 外部定义拥有内部链接</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
<p>声明为拥有外部声明的对象拥有静态<a href="c-language-storage_duration.html">存储期</a>,从而不能使用 <code>auto</code> 或 <code>register</code> 说明符。这些由外部声明引入的标识符拥有<a href="c-language-scope.html">文件作用域</a>。</p>
|
|
<h3><span class="mw-headline" id=".E8.AF.95.E6.8E.A2.E6.80.A7.E5.AE.9A.E4.B9.89">试探性定义</span></h3>
|
|
<p><i>试探性定义</i>是没有初始化器的外部声明,且要么没有<a href="c-language-storage_duration.html">存储类说明符</a>或拥有说明符 <code>static</code> 。</p>
|
|
<p><i>试探性定义</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> i1 <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// 定义,外部链接</span>
|
|
<span class="kw4">int</span> i1<span class="sy4">;</span> <span class="co1">// 试探性定义,表现为声明,因为 i1 已定义</span>
|
|
<span class="kw2">extern</span> <span class="kw4">int</span> i1<span class="sy4">;</span> <span class="co1">// 声明,引用前面的定义</span>
|
|
|
|
<span class="kw2">extern</span> <span class="kw4">int</span> i2 <span class="sy1">=</span> <span class="nu0">3</span><span class="sy4">;</span> <span class="co1">// 定义,外部链接</span>
|
|
<span class="kw4">int</span> i2<span class="sy4">;</span> <span class="co1">// 试探性定义,表现为声明,因为 i2 已定义</span>
|
|
<span class="kw2">extern</span> <span class="kw4">int</span> i2<span class="sy4">;</span> <span class="co1">// 声明,引用到前面的外部链接定义</span></pre></div>
|
|
</div>
|
|
<p>若在同一翻译单元中无定义,则试探性定义表现为拥有初始化器 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy1">=</span> <span class="nu0">0</span></span></span> (对于数组、结构、联合类型则是 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy1">=</span> <span class="br0">{</span><span class="nu0">0</span><span class="br0">}</span></span></span> )的实际定义。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">int</span> i3<span class="sy4">;</span> <span class="co1">// 试探性定义,外部链接</span>
|
|
<span class="kw4">int</span> i3<span class="sy4">;</span> <span class="co1">// 试探性定义,外部链接</span>
|
|
<span class="kw2">extern</span> <span class="kw4">int</span> i3<span class="sy4">;</span> <span class="co1">// 声明,外部链接</span>
|
|
<span class="co1">// 在此翻译单元中, i3 被如同“ int i3 = 0; ”的方式定义</span></pre></div>
|
|
</div>
|
|
<p>不同于 <a href="c-language-storage_duration.html">extern</a> 声明,若前一声明已建立标识符链接,则 extern 声明不更改链接;试探性定义可以与同一标识符另一声明的链接不一致。若同一标识符的二个声明均在作用域内且拥有不同链接,则行为未定义:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">static</span> <span class="kw4">int</span> i4 <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// 定义,内部链接</span>
|
|
<span class="kw4">int</span> i4<span class="sy4">;</span> <span class="co1">// 未定义行为:链接与前一行不一致</span>
|
|
<span class="kw2">extern</span> <span class="kw4">int</span> i4<span class="sy4">;</span> <span class="co1">// 声明,引用到内部链接定义</span>
|
|
|
|
<span class="kw4">static</span> <span class="kw4">int</span> i5<span class="sy4">;</span> <span class="co1">// 试探性定义,内部链接</span>
|
|
<span class="kw4">int</span> i5<span class="sy4">;</span> <span class="co1">// 未定义行为:链接与前一行不一致</span>
|
|
<span class="kw2">extern</span> <span class="kw4">int</span> i5<span class="sy4">;</span> <span class="co1">// 引用到前者,其链接为内部</span></pre></div>
|
|
</div>
|
|
<p>拥有内部链接的试探性定义必须拥有完整类型。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">static</span> <span class="kw4">int</span> i<span class="br0">[</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 错误:试探性 static 声明中的不完整类型</span>
|
|
<span class="kw4">int</span> i<span class="br0">[</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// OK,等价于 int i[1] = {0}; 除非在此文件之后重声明</span></pre></div>
|
|
</div>
|
|
<h3><span class="mw-headline" id=".E4.B8.80.E4.B8.AA.E5.AE.9A.E4.B9.89.E8.A7.84.E5.88.99">一个定义规则</span></h3>
|
|
<p>每个翻译单元可以拥有每个具有<a href="c-language-storage_duration.html">内部链接</a>( <code>static</code> 全局名称)的零或一个外部定义。</p>
|
|
<p>若一个具有内部链接的标识符被用于任何异于<span class="t-rev-inl t-since-c99"><span>非 VLA 的</span> <span><span class="t-mark-rev t-since-c99">(C99 起)</span></span></span> <a href="c-language-sizeof.html"><code>sizeof</code></a> <span class="t-rev-inl t-since-c11"><span>,或 <a href="c-language-_Alignof.html"><code>_Alignof</code></a></span> <span><span class="t-mark-rev t-since-c11">(C11 起)</span></span></span>的表达式,则在该翻译单元中必须有且只有一个该标识符的外部定义。</p>
|
|
<p>整个程序可以拥有每个具有<a href="c-language-storage_duration.html">外部链接</a>的标识符的零或一个外部定义。</p>
|
|
<p>若一个具有外部链接的标识符被用于任何异于<span class="t-rev-inl t-since-c99"><span>非 VLA 的</span> <span><span class="t-mark-rev t-since-c99">(C99 起)</span></span></span> <a href="c-language-sizeof.html"><code>sizeof</code></a> <span class="t-rev-inl t-since-c11"><span>,或 <a href="c-language-_Alignof.html"><code>_Alignof</code></a></span> <span><span class="t-mark-rev t-since-c11">(C11 起)</span></span></span>的表达式,则在整个程序中必须有且只有一个该标识符的外部定义。</p>
|
|
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-c99">
|
|
<td>
|
|
<p>不同翻译单元中的内联定义不受一个定义规则约束。 inline 函数定义的细节见 <a href="c-language-inline.html"><code>inline</code></a> 。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c99">(C99 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>关键词 <code>extern</code> 与文件作用域中声明在一起的含义,见<a href="c-language-storage_duration.html">存储期及链接</a>。</p>
|
|
<p>声明与定义间的区别见<a href="c-language-declarations.html#.E5.AE.9A.E4.B9.89">定义</a>。</p>
|
|
<p>发明试探性定义是为了标准化各种 C89 前的前置声明具有内部链接标识符的手段。</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>6.9 External definitions (p: 155-159)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<div class="t-ref-std-c99">
|
|
<ul>
|
|
<li>C99 标准(ISO/IEC 9899:1999):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.9 External definitions (p: 140-144)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
<div class="t-ref-std-c89">
|
|
<ul>
|
|
<li>C89/C90 标准(ISO/IEC 9899:1990):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>3.7 EXTERNAL DEFINITIONS</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|