175 lines
18 KiB
HTML
175 lines
18 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>const 类型限定符</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_const skin-cppreference2 action-view cpp-navbar">
|
|
<div id="cpp-content-base">
|
|
<div id="content"><a id="top"></a>
|
|
<h1 id="firstHeading" class="firstHeading">const 类型限定符</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>C <a href="c-language-type.html" class="mw-redirect">类型系统</a>中每一个独立的类型在都有数个该类型的<i>限定</i>版本,对应 <i>const</i> 、 <a href="c-language-volatile.html">volatile</a> 及对于指向对象指针的 <a href="c-language-restrict.html">restrict</a> 限定符中的一个、两个或全部三个。此页面描述 <i>const</i> 限定符的效果。</p>
|
|
<p>编译器可以把<a href="c-language-declarations.html">声明</a>带 const 限定类型的对象放到只读内存中,而且若程序决不取该 const 对象的地址,则可能完全不存储它。</p>
|
|
<p><code>const</code> 语义仅应用到<a href="c-language-value_category.html">左值</a>表达式;只要在不要求左值的语境中使用 const 左值表达式,就会丢失其 <code>const</code> 限定符(注意不丢失 <code>volatile</code> 限定符,若它存在)。</p>
|
|
<p>指代 const 限定类型对象的左值表达式,和指代拥有至少一个 const 限定类型成员(包含为聚合体或联合体所递归含有的成员)的结构体或联合体的左值表达式,不是<i>可修改左值</i>。具体而言,它们不可赋值:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">const</span> <span class="kw4">int</span> n <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// const 类型对象</span>
|
|
n <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// 错误: n 的类型为 const 限定</span>
|
|
|
|
<span class="kw4">int</span> x <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// 无限定类型对下</span>
|
|
<span class="kw4">const</span> <span class="kw4">int</span><span class="sy2">*</span> p <span class="sy1">=</span> <span class="sy3">&</span>x<span class="sy4">;</span>
|
|
<span class="sy2">*</span>p <span class="sy1">=</span> <span class="nu0">3</span><span class="sy4">;</span> <span class="co1">// 错误:左值 *p 的类型为 const 限定</span>
|
|
|
|
<span class="kw1">struct</span> <span class="br0">{</span><span class="kw4">int</span> a<span class="sy4">;</span> <span class="kw4">const</span> <span class="kw4">int</span> b<span class="sy4">;</span> <span class="br0">}</span> s1 <span class="sy1">=</span> <span class="br0">{</span>.<span class="me1">b</span><span class="sy1">=</span><span class="nu0">1</span><span class="br0">}</span>, s2 <span class="sy1">=</span> <span class="br0">{</span>.<span class="me1">b</span><span class="sy1">=</span><span class="nu0">2</span><span class="br0">}</span><span class="sy4">;</span>
|
|
s1 <span class="sy1">=</span> s2<span class="sy4">;</span> <span class="co1">// 错误: s1 的类型无限定,但它有 const 成员</span></pre></div>
|
|
</div>
|
|
<p>const 限定的结构体或联合体类型的成员,取得它所属类型的限定版本(在用 <code><b>.</b></code> 运算符或 <code><b>-></b></code> 运算符访问时)。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw1">struct</span> s <span class="br0">{</span> <span class="kw4">int</span> i<span class="sy4">;</span> <span class="kw4">const</span> <span class="kw4">int</span> ci<span class="sy4">;</span> <span class="br0">}</span> s<span class="sy4">;</span>
|
|
<span class="co1">// s.i 的类型为 int , s.ci 的类型为 const int</span>
|
|
<span class="kw4">const</span> <span class="kw1">struct</span> s cs<span class="sy4">;</span>
|
|
<span class="co1">// cs.i 和 cs.ci 的类型都是 const int</span></pre></div>
|
|
</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-until-c23">
|
|
<td>
|
|
<p>若以 const 类型限定符声明数组类型(通过使用 <a href="c-language-typedef.html">typedef</a> ),则数组类型无 const 限定,但其元素类型有。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-until-c23">(C23 前)</span></td>
|
|
</tr>
|
|
<tr class="t-rev t-since-c23">
|
|
<td>
|
|
<p>始终认为数组类型与其元素类型同等地拥有 const 限定。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c23">(C23 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>若以 const 类型限定符声明函数类型(通过使用 <a href="c-language-typedef.html">typedef</a> ),则行为未定义。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw1">typedef</span> <span class="kw4">int</span> A<span class="br0">[</span><span class="nu0">2</span><span class="br0">]</span><span class="br0">[</span><span class="nu0">3</span><span class="br0">]</span><span class="sy4">;</span>
|
|
<span class="kw4">const</span> A a <span class="sy1">=</span> <span class="br0">{</span><span class="br0">{</span><span class="nu0">4</span>, <span class="nu0">5</span>, <span class="nu0">6</span><span class="br0">}</span>, <span class="br0">{</span><span class="nu0">7</span>, <span class="nu0">8</span>, <span class="nu0">9</span><span class="br0">}</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// const int 的数组的数组</span>
|
|
<span class="kw4">int</span><span class="sy2">*</span> pi <span class="sy1">=</span> a<span class="br0">[</span><span class="nu0">0</span><span class="br0">]</span><span class="sy4">;</span> <span class="co1">// 错误: a[0] 拥有 const int* 类型</span>
|
|
<span class="kw4">void</span> <span class="sy2">*</span>unqual_ptr <span class="sy1">=</span> a<span class="sy4">;</span> <span class="co1">// C23 前 OK ; C23 起错误</span>
|
|
<span class="co1">// 注: clang 即使在 C89-C17 模式也应用 C++/C23 中的规则</span></pre></div>
|
|
</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-c99">
|
|
<td>
|
|
<p>const 限定的复合字面量不必指代相异的对象;能与恰好拥有重叠表示的其他复合字面量和字符串字面量一同存储它们。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">const</span> <span class="kw4">int</span><span class="sy2">*</span> p1 <span class="sy1">=</span> <span class="br0">(</span><span class="kw4">const</span> <span class="kw4">int</span><span class="br0">[</span><span class="br0">]</span><span class="br0">)</span><span class="br0">{</span><span class="nu0">1</span>, <span class="nu0">2</span>, <span class="nu0">3</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw4">const</span> <span class="kw4">int</span><span class="sy2">*</span> p2 <span class="sy1">=</span> <span class="br0">(</span><span class="kw4">const</span> <span class="kw4">int</span><span class="br0">[</span><span class="br0">]</span><span class="br0">)</span><span class="br0">{</span><span class="nu0">2</span>, <span class="nu0">3</span>, <span class="nu0">4</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// p2 的值可等于 p1+1</span>
|
|
_Bool b <span class="sy1">=</span> <span class="st0">"foobar"</span> <span class="sy2">+</span> <span class="nu0">3</span> <span class="sy1">==</span> <span class="br0">(</span><span class="kw4">const</span> <span class="kw4">char</span><span class="br0">[</span><span class="br0">]</span><span class="br0">)</span><span class="br0">{</span><span class="st0">"bar"</span><span class="br0">}</span><span class="sy4">;</span> <span class="co1">// b 的值可为 1</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c99">(C99 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>指向非 const 类型的指针能隐式转换成指向同一或<a href="c-language-type.html#.E5.85.BC.E5.AE.B9.E7.B1.BB.E5.9E.8B" class="mw-redirect">兼容</a>类型的 const 限定版本的指针。能用转型表达式进行逆向转换。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">int</span><span class="sy2">*</span> p <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
|
<span class="kw4">const</span> <span class="kw4">int</span><span class="sy2">*</span> cp <span class="sy1">=</span> p<span class="sy4">;</span> <span class="co1">// OK :添加限定符( int 到 const int )</span>
|
|
p <span class="sy1">=</span> cp<span class="sy4">;</span> <span class="co1">// 错误:舍弃限定符( const int 到 int )</span>
|
|
p <span class="sy1">=</span> <span class="br0">(</span><span class="kw4">int</span><span class="sy2">*</span><span class="br0">)</span>cp<span class="sy4">;</span> <span class="co1">// OK :转型</span></pre></div>
|
|
</div>
|
|
<p>注意指向指向 <code>T</code> 指针的指针不可转换为指向指向 <code>const T</code> 指针的指针;对于要兼容的二个类型,其限定必须等同。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">char</span> <span class="sy2">*</span>p <span class="sy1">=</span> <span class="nu0">0</span><span class="sy4">;</span>
|
|
<span class="kw4">const</span> <span class="kw4">char</span> <span class="sy2">**</span>cpp <span class="sy1">=</span> <span class="sy3">&</span>p<span class="sy4">;</span> <span class="co1">// 错误: char* 与 const char* 不是兼容类型</span>
|
|
<span class="kw4">char</span> <span class="sy2">*</span> <span class="kw4">const</span> <span class="sy2">*</span>pcp <span class="sy1">=</span> <span class="sy3">&</span>p<span class="sy4">;</span> <span class="co1">// OK :添加限定符( char * 到 char *const )</span></pre></div>
|
|
</div>
|
|
<p>任何修改有 const 限定类型的对象的尝试导致未定义行为。</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">const</span> <span class="kw4">int</span> n <span class="sy1">=</span> <span class="nu0">1</span><span class="sy4">;</span> <span class="co1">// const 限定类型对象</span>
|
|
<span class="kw4">int</span><span class="sy2">*</span> p <span class="sy1">=</span> <span class="br0">(</span><span class="kw4">int</span><span class="sy2">*</span><span class="br0">)</span><span class="sy3">&</span>n<span class="sy4">;</span>
|
|
<span class="sy2">*</span>p <span class="sy1">=</span> <span class="nu0">2</span><span class="sy4">;</span> <span class="co1">// 未定义行为</span></pre></div>
|
|
</div>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-c99">
|
|
<td>
|
|
<p>函数声明中,关键词 <code>const</code> 可出现在用于声明数组类型函数参数的方括号内。它限定数组类型变换到的指针类型。</p>
|
|
<p>下列二个声明声明同一函数:</p>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">double</span> x<span class="br0">[</span><span class="kw4">const</span><span class="br0">]</span>, <span class="kw4">const</span> <span class="kw4">double</span> y<span class="br0">[</span><span class="kw4">const</span><span class="br0">]</span><span class="br0">)</span><span class="sy4">;</span>
|
|
<span class="kw4">void</span> f<span class="br0">(</span><span class="kw4">double</span> <span class="sy2">*</span> <span class="kw4">const</span> x, <span class="kw4">const</span> <span class="kw4">double</span> <span class="sy2">*</span> <span class="kw4">const</span> y<span class="br0">)</span><span class="sy4">;</span></pre></div>
|
|
</div>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c99">(C99 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E5.85.B3.E9.94.AE.E8.AF.8D">关键词</span></h3>
|
|
<p><a href="c-keyword-const.html"><tt>const</tt></a></p>
|
|
<h3><span class="mw-headline" id=".E6.B3.A8.E8.A7.A3">注解</span></h3>
|
|
<p>C 从 C++ 接纳了 <i>const</i> 限定符,但不同于 C++ 中, C 中 const 限定类型的表达式不是<a href="c-language-constant_expression.html">常量表达式</a>;它们不可用作 <a href="c-language-switch.html">case</a> 标号,或用于初始化<a href="c-language-storage_duration.html">静态</a>和<a href="c-language-storage_duration.html">线程</a>存储期对象、用作<a href="c-language-enum.html">枚举项</a>或<a href="c-language-bit_field.html">位域</a>大小。以之为<a href="c-language-array.html">数组</a>大小是,产生的数组为 VLA 。</p>
|
|
<h3><span class="mw-headline" id=".E5.BC.95.E7.94.A8">引用</span></h3>
|
|
<div class="t-ref-std-17">
|
|
<ul>
|
|
<li>C17 标准(ISO/IEC 9899:2018):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.7.3 Type qualifiers (p: 87-90)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="t-ref-std-11">
|
|
<ul>
|
|
<li>C11 标准(ISO/IEC 9899:2011):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.7.3 Type qualifiers (p: 121-123)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="t-ref-std-c99">
|
|
<ul>
|
|
<li>C99 标准(ISO/IEC 9899:1999):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.7.3 Type qualifiers (p: 108-110)</li>
|
|
</ul>
|
|
</dd>
|
|
</dl>
|
|
</div>
|
|
<div class="t-ref-std-c89">
|
|
<ul>
|
|
<li>C89/C90 标准(ISO/IEC 9899:1990):</li>
|
|
</ul>
|
|
<dl>
|
|
<dd>
|
|
<ul>
|
|
<li>6.5.3 Type qualifiers</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 class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|