219 lines
17 KiB
HTML
219 lines
17 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_bit_field 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>声明拥有以位数表示的显式宽度的成员。相邻的位域成员可能被打包,共享和分散到单独的字节。</p>
|
|
<p>位域声明是使用下列<a href="c-language-declarations.html">声明器</a>的<a href="c-language-struct.html">结构体</a>或<a href="c-language-union.html">联合体</a>成员声明:</p>
|
|
<table class="t-sdsc-begin">
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
<tr class="t-sdsc">
|
|
<td class="t-sdsc-nopad"><span class="t-spar">标识符</span><span class="t-mark">(可选)</span> <code><b>:</b></code> <span class="t-spar">宽度</span></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
<td class="t-sdsc-nopad"></td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="10" class="t-sdsc-sep"></td>
|
|
</tr>
|
|
</table>
|
|
<table class="t-par-begin">
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">标识符</span></td>
|
|
<td>-</td>
|
|
<td>正在声明的位域名称。名称是可选的:无名位域引入一个指定的填充位数</td>
|
|
</tr>
|
|
<tr class="t-par">
|
|
<td><span class="t-spar">宽度</span></td>
|
|
<td>-</td>
|
|
<td>一个拥有大于或等于零,且小于或等于底层类型位数的整数<a href="c-language-constant_expression.html">常量表达式</a>。大于零时,此为此位域将占据的位数。零值仅允许用于无名位域,并拥有特殊含义:它指定结构体定义中的下个位域会从分配单元边界开始。</td>
|
|
</tr>
|
|
</table>
|
|
<h3><span class="mw-headline" id=".E8.A7.A3.E9.87.8A">解释</span></h3>
|
|
<p>位域可以拥有四种类型之一(可为 <a href="c-language-const.html">const</a> 或 <a href="c-language-volatile.html">volatile</a> 限定):</p>
|
|
<ul>
|
|
<li><span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">unsigned</span> <span class="kw4">int</span></span></span> ,对于无符号位域( <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">unsigned</span> <span class="kw4">int</span> b<span class="sy4">:</span><span class="nu0">3</span><span class="sy4">;</span></span></span> 拥有范围 <span class="t-c"><span class="mw-geshi c source-c"><span class="nu0">0</span>..<span class="nu0">7</span></span></span> )</li>
|
|
<li><span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">signed</span> <span class="kw4">int</span></span></span> ,对于有符号位域( <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">signed</span> <span class="kw4">int</span> b<span class="sy4">:</span><span class="nu0">3</span><span class="sy4">;</span></span></span> 拥有范围 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy2">-</span><span class="nu0">4</span>..<span class="nu0">3</span></span></span> )</li>
|
|
<li><span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">int</span></span></span> ,对于拥有实现定义符号性的位域(注意这与其他所有地方都表示“ <code>signed int</code> ”的关键词 <code>int</code> 含义不同)。例如, <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">int</span> b<span class="sy4">:</span><span class="nu0">3</span><span class="sy4">;</span></span></span> 可能拥有 <span class="t-c"><span class="mw-geshi c source-c"><span class="nu0">0</span>..<span class="nu0">7</span></span></span> 或 <span class="t-c"><span class="mw-geshi c source-c"><span class="sy2">-</span><span class="nu0">4</span>..<span class="nu0">3</span></span></span> 范围的值。</li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-c99">
|
|
<td>
|
|
<ul>
|
|
<li><span class="t-c"><span class="mw-geshi c source-c">_Bool</span></span> ,对于单个位的位域( <span class="t-c"><span class="mw-geshi c source-c">bool x<span class="sy4">:</span><span class="nu0">1</span><span class="sy4">;</span></span></span> 拥有范围 <span class="t-c"><span class="mw-geshi c source-c"><span class="nu0">0</span>..<span class="nu0">1</span></span></span> ),来自它和到它的<a href="c-language-conversion.html">隐式转换</a>遵循布尔转换规则。</li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c99">(C99 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>可接受额外的实现定义类型。<span class="t-rev-inl t-since-c11"><span>位域是否可以拥有<a href="c-language-atomic.html">原子</a>类型也是实现定义的。</span> <span><span class="t-mark-rev t-since-c11">(C11 起)</span></span></span>位域中的位数( <span class="t-spar">宽度</span> )限制其所能保有的值域:</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="co2">#include <stdio.h></span>
|
|
<span class="kw1">struct</span> S <span class="br0">{</span>
|
|
<span class="co1">// 三位无符号位域,允许值为 0..7</span>
|
|
<span class="kw4">unsigned</span> <span class="kw4">int</span> b <span class="sy4">:</span> <span class="nu0">3</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<span class="kw1">struct</span> S s <span class="sy1">=</span> <span class="br0">{</span><span class="nu0">7</span><span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="sy2">++</span>s.<span class="me1">b</span><span class="sy4">;</span> <span class="co1">// 无符号溢出</span>
|
|
<a href="c-io-fprintf.html"><span class="kw851">printf</span></a><span class="br0">(</span><span class="st0">"%d<span class="es1">\n</span>"</span>, s.<span class="me1">b</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 输出: 0</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
</div>
|
|
<p>允许将多个相邻位域打包在一起(通常如此):</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="co2">#include <stdio.h></span>
|
|
<span class="kw1">struct</span> S <span class="br0">{</span>
|
|
<span class="co1">// 通常将占用 4 字节:</span>
|
|
<span class="co1">// 5 位: b1 的值</span>
|
|
<span class="co1">// 11 位:未使用</span>
|
|
<span class="co1">// 6 位: b2 的值</span>
|
|
<span class="co1">// 2 位: b3 的值</span>
|
|
<span class="co1">// 8 位:未使用</span>
|
|
<span class="kw4">unsigned</span> b1 <span class="sy4">:</span> <span class="nu0">5</span>, <span class="sy4">:</span> <span class="nu0">11</span>, b2 <span class="sy4">:</span> <span class="nu0">6</span>, b3 <span class="sy4">:</span> <span class="nu0">2</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<a href="c-io-fprintf.html"><span class="kw851">printf</span></a><span class="br0">(</span><span class="st0">"%zu<span class="es1">\n</span>"</span>,<span class="kw4">sizeof</span><span class="br0">(</span><span class="kw1">struct</span> S<span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 通常打印 4</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
</div>
|
|
<p>拥有零 <span class="t-spar">宽度</span> 的特殊<i>无名位域</i>打破填充:它指定下个位域在始于下个分配单元的起点:</p>
|
|
<div class="t-example">
|
|
<div class="t-example-live-link"></div>
|
|
<div dir="ltr" class="mw-geshi" style="text-align: left;">
|
|
<div class="c source-c">
|
|
<pre class="de1"><span class="co2">#include <stdio.h></span>
|
|
<span class="kw1">struct</span> S <span class="br0">{</span>
|
|
<span class="co1">// 通常将占用 8 字节</span>
|
|
<span class="co1">// 5 位: b1 的值</span>
|
|
<span class="co1">// 27 位:未使用</span>
|
|
<span class="co1">// 6 位: b2 的值</span>
|
|
<span class="co1">// 15 位: b3 的值</span>
|
|
<span class="co1">// 11 位:未使用</span>
|
|
<span class="kw4">unsigned</span> b1 <span class="sy4">:</span> <span class="nu0">5</span><span class="sy4">;</span>
|
|
<span class="kw4">unsigned</span> <span class="sy4">:</span><span class="nu0">0</span><span class="sy4">;</span> <span class="co1">// 开始新的 unsigned int</span>
|
|
<span class="kw4">unsigned</span> b2 <span class="sy4">:</span> <span class="nu0">6</span><span class="sy4">;</span>
|
|
<span class="kw4">unsigned</span> b3 <span class="sy4">:</span> <span class="nu0">15</span><span class="sy4">;</span>
|
|
<span class="br0">}</span><span class="sy4">;</span>
|
|
<span class="kw4">int</span> main<span class="br0">(</span><span class="kw4">void</span><span class="br0">)</span>
|
|
<span class="br0">{</span>
|
|
<a href="c-io-fprintf.html"><span class="kw851">printf</span></a><span class="br0">(</span><span class="st0">"%zu<span class="es1">\n</span>"</span>, <span class="kw4">sizeof</span><span class="br0">(</span><span class="kw1">struct</span> S<span class="br0">)</span><span class="br0">)</span><span class="sy4">;</span> <span class="co1">// 通常打印 8</span>
|
|
<span class="br0">}</span></pre></div>
|
|
</div>
|
|
</div>
|
|
<p>因为位域不必在字节的起点开始,故不能取位域的地址。不可能有指向位域的指针。不能对位域使用 <a href="c-language-sizeof.html"><code>sizeof</code></a> <span class="t-rev-inl t-since-c11"><span>和 <a href="c-language-_Alignas.html"><code>_Alignas</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>
|
|
<p>位域的下列属性<i>未定义</i>:</p>
|
|
<ul>
|
|
<li>在位域上调用 <span class="t-lc"><a href="c-types-offsetof.html">offsetof</a></span> 的效果</li>
|
|
</ul>
|
|
<p>位域的下列属性<i>未指定</i>:</p>
|
|
<ul>
|
|
<li>保有位域的分配单元的对齐</li>
|
|
</ul>
|
|
<p>位域的下列属性为<i>实现定义</i>:</p>
|
|
<ul>
|
|
<li><span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">int</span></span></span> 类型的位域被当做有符号或无符号</li>
|
|
<li>是否容许异于 <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">int</span></span></span> 、 <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">signed</span> <span class="kw4">int</span></span></span> 、 <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">unsigned</span> <span class="kw4">int</span></span></span> <span class="t-rev-inl t-since-c99"><span>及 <span class="t-c"><span class="mw-geshi c source-c">_Bool</span></span></span> <span><span class="t-mark-rev t-since-c99">(C99 起)</span></span></span> 类型的位域</li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-c11">
|
|
<td>
|
|
<ul>
|
|
<li>是否容许原子类型的位域</li>
|
|
</ul>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c11">(C11 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<ul>
|
|
<li>位域是否能越过分配单元边界</li>
|
|
<li>分配单元内位域的顺序(一些平台上位域从左往右打包,其他平台上是从右往左)</li>
|
|
</ul>
|
|
<table class="t-rev-begin">
|
|
<tr class="t-rev t-since-c99">
|
|
<td>
|
|
<p>尽管 <code>_Bool</code> 的对象表示的位数至少为 <span class="t-lc"><a href="c-types-limits.html">CHAR_BIT</a></span> , <code>_Bool</code> 类型位域的 <span class="t-spar">宽度</span> 不能大于 1 。</p>
|
|
</td>
|
|
<td><span class="t-mark-rev t-since-c99">(C99 起)</span></td>
|
|
</tr>
|
|
</table>
|
|
<p>C++ 编程语言中,位域的宽度能超出底层类型,并且 <span class="t-c"><span class="mw-geshi c source-c"><span class="kw4">int</span></span></span> 类型的位域始终为有符号。</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.2.1 Structure and union specifiers</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.2.1 Structure and union specifiers</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.2.1 Structure and union specifiers</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>3.5.2.1 Structure and union specifiers</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>
|