<?xml version="1.0" encoding="gbk"?> <rss version="2.0"><channel> <title>定阅帖子更新</title> <link>http://www.broadkey.com.cn/XML.ASP</link><description>TEAM Board - 意得法电子</description> <copyright>TEAM 2.0.5 Release</copyright><generator>TEAM Board by TEAM5.Cn Studio</generator> <ttl>30</ttl><item><link>http://www.broadkey.com.cn/Thread.asp?tid=439 </link><title>C语言中sizeof详解--面试C/C++者必读</title><author>幻影</author><pubDate>2009-12-15 11:49:21</pubDate><description><![CDATA[<div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">大部分公司在招聘技术职位面试的时候，都会考</span><span style="font-size: 12pt">c</span><span style="font-size: 12pt">语言基础，而</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">是他们最喜欢考的知识点，现总结如下：</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">1</span></strong><strong><span style="font-size: 14pt">、定义</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">是</span><span style="font-size: 12pt">C</span><span style="font-size: 12pt">语言的一种单目操作符，它并不是函数。</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">操作符以字节形式给出了其操作数所占存储空间的大小。操作数可以是一个表达式或括在括号内的类型名。操作数所占存储空间的大小由操作数的类型决定。作用就是返回一个对象或者类型所占的内存字节数。</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">2</span></strong><strong><span style="font-size: 14pt">、语法</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">有如下三种语法形式：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(1) sizeof( object ); // sizeof( </span><span style="font-size: 12pt">对象</span><span style="font-size: 12pt"> );</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(2) sizeof( type_name ); // sizeof( </span><span style="font-size: 12pt">类型</span><span style="font-size: 12pt"> );</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(3) sizeof object; // sizeof </span><span style="font-size: 12pt">对象</span><span style="font-size: 12pt">;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">所以，</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int i;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( i );&nbsp;&nbsp;&nbsp; // ok</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// ok</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( int );&nbsp;&nbsp;// ok</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof int;&nbsp;&nbsp;&nbsp;&nbsp; // error</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">实际上，</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">计算对象的大小也是转换成对对象类型的计算，也就是说，同种类型的不同对象其</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值都是一致的。这里，对象可以进一步延伸至表达式，即</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">可以对一个表达式求值，编译器根据表达式的最终结果类型来确定大小，一般不会对表达式进行计算。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">如：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof(2);&nbsp;&nbsp;//2</span><span style="font-size: 12pt">的类型为</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">，所以等价于</span><span style="font-size: 12pt"> sizeof( int );</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( 2 + 3.14 ); // 3.14</span><span style="font-size: 12pt">的类型为</span><span style="font-size: 12pt">double</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">也会被提升成</span><span style="font-size: 12pt">double</span><span style="font-size: 12pt">类型，所以等价于</span><span style="font-size: 12pt"> sizeof( double );</span></div>
<div style="line-height: 20pt"><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">也可以对一个函数调用求值，其结果是函数返回类型的大小，函数并不会被调用，我们来看一个完整的例子：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">char foo()</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">printf(&quot;foo() has been called.\n&quot;);</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">return 'a';</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">}</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int main()</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 42pt"><span style="font-size: 12pt">sz = sizeof( foo() ); </span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 42pt"><span style="font-size: 12pt">/*foo() </span><span style="font-size: 12pt">的返回值类型为</span><span style="font-size: 12pt">char</span><span style="font-size: 12pt">，所以</span><span style="font-size: 12pt">sz = sizeof(char )</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">foo()</span><span style="font-size: 12pt">并不会被调</span><span style="font-size: 12pt">*/</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">printf(&quot;sizeof( foo() ) = %d\n&quot;, sz);</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">}</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">C99</span><span style="font-size: 12pt">标准规定，函数、不能确定类型的表达式以及位域（</span><span style="font-size: 12pt">bit-field</span><span style="font-size: 12pt">）成员不能被计算</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值，即</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">操作符不能用于函数类型，不完全类型或位字段。不完全类型指具有未知存储大小的数据类型，如未知存储大小的数组类型、未知内容的结构或联合类型、</span><span style="font-size: 12pt">void</span><span style="font-size: 12pt">类型等。下面这些写法都是错误的：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( foo );&nbsp;&nbsp;// error</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">void foo2() { }</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( foo2() );&nbsp;&nbsp;// error</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct S</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">unsigned int f1 : 1;&nbsp;&nbsp;// error </span><span style="font-size: 12pt">属于位字段</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">unsigned int f2 : 5;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">unsigned int f3 : 12;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( S.f1 );&nbsp;&nbsp;// error</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">3</span></strong><strong><span style="font-size: 14pt">、</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong><strong><span style="font-size: 14pt">的常量性</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">的计算发生在编译时刻，所以它可以被当作常量表达式使用，如：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">char ary[ sizeof( int ) * 10 ]; // ok</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">最新的</span><span style="font-size: 12pt">C99</span><span style="font-size: 12pt">标准规定</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">也可以在运行时刻进行计算，如下面的程序在</span><span style="font-size: 12pt">Dev-C++</span><span style="font-size: 12pt">中可以正确执行：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int n;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">n = 10; // n</span><span style="font-size: 12pt">动态赋值</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">char ary[n]; // C99</span><span style="font-size: 12pt">也支持数组的动态定义</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">printf(&quot;%d\n&quot;, sizeof(ary)); // ok. </span><span style="font-size: 12pt">输出</span><span style="font-size: 12pt">10</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">但在没有完全实现</span><span style="font-size: 12pt">C99</span><span style="font-size: 12pt">标准的编译器中就行不通了，上面的代码在</span><span style="font-size: 12pt">VC6</span><span style="font-size: 12pt">中就通不过编译。所以我们最好还是认为</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">是在编译期执行的，这样不会带来错误，让程序的可移植性强些。</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">4</span></strong><strong><span style="font-size: 14pt">、基本数据类型的</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">这里的基本数据类型指</span><span style="font-size: 12pt">short</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">long</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">float</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">double</span><span style="font-size: 12pt">这样的简单内置数据类型，由于它们都是和系统相关的，所以在不同的系统下取值可能不同，这务必引起我们的注意，尽量不要在这方面给自己程序的移植造成麻烦。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">一般的，在</span><span style="font-size: 12pt">32</span><span style="font-size: 12pt">位编译环境中，</span><span style="font-size: 12pt">sizeof(int)</span><span style="font-size: 12pt">的取值为</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">5</span></strong><strong><span style="font-size: 14pt">、指针变量的</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">指针是来存放地址的，那么</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">指针变量当然等于计算机内部地址总线的宽度。所以在</span><span style="font-size: 12pt">32</span><span style="font-size: 12pt">位计算机中，一个指针变量的返回值必定是</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">（注意结果是以字节为单位），可以预计，在将来的</span><span style="font-size: 12pt">64</span><span style="font-size: 12pt">位系统中指针变量的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">8</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">char* pc = &quot;abc&quot;;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int* pi;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">string* ps;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">char** ppc = &amp;pc;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">void (*pf)();&nbsp;&nbsp;// </span><span style="font-size: 12pt">函数指针</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( pc );&nbsp;&nbsp;// </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">4</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( pi );&nbsp;&nbsp;// </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">4</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( ps );&nbsp;&nbsp;// </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">4</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( ppc ); // </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">4</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( pf );&nbsp;&nbsp;// </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">4</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">指针变量的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值与指针所指的对象没有任何关系。</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">6</span></strong><strong><span style="font-size: 14pt">、数组的</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">数组的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值等于数组所占用的内存字节数，如：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">char a1[] = &quot;abc&quot;;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int a2[3];</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( a1 ); // </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">，字符末尾还存在一个</span><span style="font-size: 12pt">NULL</span><span style="font-size: 12pt">终止符</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">sizeof( a2 ); // </span><span style="font-size: 12pt">结果为</span><span style="font-size: 12pt">3*4=12</span><span style="font-size: 12pt">（依赖于</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">）</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">一些朋友刚开始时把</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">当作了求数组元素的个数，现在，你应该知道这是不对的，那么应该怎么求数组元素的个数呢？通常有下面两种写法：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int c1 = sizeof( a1 ) / sizeof( char ); // </span><span style="font-size: 12pt">总长度</span><span style="font-size: 12pt">/</span><span style="font-size: 12pt">单个元素的长度</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">int c2 = sizeof( a1 ) / sizeof( a1[0] ); // </span><span style="font-size: 12pt">总长度</span><span style="font-size: 12pt">/</span><span style="font-size: 12pt">第一个元素的长度</span></div>
<div style="line-height: 20pt"><span style="font-size: 12pt">写到这里，提一问，下面的</span><span style="font-size: 12pt">c3</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">c4</span><span style="font-size: 12pt">值应该是多少呢？</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">void foo3(char a3[3])</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">int c3 = sizeof( a3 ); // c3 ==</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">}</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">void foo4(char a4[])</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">int c4 = sizeof( a4 ); // c4 ==</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">}</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">也许当你试图回答</span><span style="font-size: 12pt">c4</span><span style="font-size: 12pt">的值时已经意识到</span><span style="font-size: 12pt">c3</span><span style="font-size: 12pt">答错了，是的，</span><span style="font-size: 12pt">c3!=3</span><span style="font-size: 12pt">。这里函数参数</span><span style="font-size: 12pt">a3</span><span style="font-size: 12pt">已不再是数组类型，而是蜕变成指针，相当于</span><span style="font-size: 12pt">char* a3</span><span style="font-size: 12pt">，为什么？仔细想想就不难明白，我们调用函数</span><span style="font-size: 12pt">foo3</span><span style="font-size: 12pt">时，程序会在栈上分配一个大小为</span><span style="font-size: 12pt">3</span><span style="font-size: 12pt">的数组吗不会！数组是</span><span style="font-size: 12pt">&ldquo;</span><span style="font-size: 12pt">传址</span><span style="font-size: 12pt">&rdquo;</span><span style="font-size: 12pt">的，调用者只需将实参的地址传递过去，所以</span><span style="font-size: 12pt">a3</span><span style="font-size: 12pt">自然为指针类型</span><span style="font-size: 12pt">(char*</span><span style="font-size: 12pt">），</span><span style="font-size: 12pt">c3</span><span style="font-size: 12pt">的值也就为</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">7</span></strong><strong><span style="font-size: 14pt">、结构体的</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">这是初学者问得最多的一个问题，所以这里有必要多费点笔墨。让我们先看一个结构体</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct S1</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">int i;</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">问</span><span style="font-size: 12pt">sizeof(s1)</span><span style="font-size: 12pt">等于多少聪明的你开始思考了，</span><span style="font-size: 12pt">char</span><span style="font-size: 12pt">占</span><span style="font-size: 12pt">1</span><span style="font-size: 12pt">个字节，</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">占</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">个字节，那么加起来就应该是</span><span style="font-size: 12pt">5</span><span style="font-size: 12pt">。是这样吗？你在你机器上试过了吗？也许你是对的，但很可能你是错的！</span><span style="font-size: 12pt">VC6</span><span style="font-size: 12pt">中按默认设置得到的结果为</span><span style="font-size: 12pt">8</span><span style="font-size: 12pt">。这是因为结构体遵循字节对齐原则，为什么需要字节对齐？计算机组成原理教导我们这样有助于加快计算机的取数速度，否则就得多花指令周期了。为此，编译器默认会对结构体进行处理（实际上其它地方的数据变量也是如此），让宽度为</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">的基本数据类型（</span><span style="font-size: 12pt">short</span><span style="font-size: 12pt">等）都位于能被</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">整除的地址上，让宽度为</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">的基本数据类型（</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">等）都位于能被</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">整除的地址上，以此类推。这样，两个数中间就可能需要加入填充字节，所以整个结构体的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值就增长了。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">字节对齐的细节和编译器实现相关，但一般而言，满足三个准则：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(1) </span><span style="font-size: 12pt">结构体变量的首地址能够被其最宽基本类型成员的大小所整除；</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(2) </span><span style="font-size: 12pt">结构体每个成员相对于结构体首地址的偏移量（</span><span style="font-size: 12pt">offset</span><span style="font-size: 12pt">）都是成员大小的整数倍，如有需要编译器会在成员之间加上填充字节（</span><span style="font-size: 12pt">internal adding</span><span style="font-size: 12pt">）；</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(3) </span><span style="font-size: 12pt">结构体的总大小为结构体最宽基本类型成员大小的整数倍，如有需要编译器会在最末一个成员之后加上填充字节（</span><span style="font-size: 12pt">trailing padding</span><span style="font-size: 12pt">）。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">由于结构体的成员可以是复合类型，比如另外一个结构体，所以在寻找最宽基本类型成员时，应当包括复合类型成员的子成员，而不是把复合成员看成是一个整体。但在确定复合类型成员的偏移位置时则是将复合类型作为整体看待。</span></div>
<div style="line-height: 20pt"><span style="font-size: 12pt">这里叙述起来有点拗口，思考起来也有点挠头，还是让我们看看例子吧：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct S3</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c1;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">S1 s;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c2</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">S1</span><span style="font-size: 12pt">的最宽简单成员的类型为</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">S3</span><span style="font-size: 12pt">在考虑最宽简单类型成员时是将</span><span style="font-size: 12pt">S1&ldquo;</span><span style="font-size: 12pt">打散</span><span style="font-size: 12pt">&rdquo;</span><span style="font-size: 12pt">看的，所以</span><span style="font-size: 12pt">S3</span><span style="font-size: 12pt">的最宽简单类型为</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">，这样，通过</span><span style="font-size: 12pt">S3</span><span style="font-size: 12pt">定义的变量，其存储空间首地址需要被</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">整除，整个</span><span style="font-size: 12pt">sizeof(S3)</span><span style="font-size: 12pt">的值也应该被</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">整除。</span><span style="font-size: 12pt">sizeof(S3)</span><span style="font-size: 12pt">的值为</span><span style="font-size: 12pt">16</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">到这里，朋友们应该对结构体的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">有了一个全新的认识，但不要高兴得太早，有一个影响</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">的重要参量还未被提及，那便是编译器的</span><span style="font-size: 12pt">pack</span><span style="font-size: 12pt">指令。它是用来调整结构体对齐方式的，不同编译器名称和用法略有不同，</span><span style="font-size: 12pt">VC6</span><span style="font-size: 12pt">中通过</span><span style="font-size: 12pt">#pragma pack</span><span style="font-size: 12pt">实现，也可以直接修改</span><span style="font-size: 12pt">/Zp</span><span style="font-size: 12pt">编译开关。</span><span style="font-size: 12pt">#pragma pack</span><span style="font-size: 12pt">的基本用法为：</span><span style="font-size: 12pt">#pragma pack( n )</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">n</span><span style="font-size: 12pt">为字节对齐数，其取值为</span><span style="font-size: 12pt">1</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">4</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">8</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">16</span><span style="font-size: 12pt">，默认是</span><span style="font-size: 12pt">8</span><span style="font-size: 12pt">，如果这个值比结构体成员的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值小，那么该成员的偏移量应该以此值为准，即是说，结构体成员的偏移量应该取二者的最小值，公式如下：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">offsetof( item ) = min( n, sizeof( item ) )</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">再看示例：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">#pragma pack(push) // </span><span style="font-size: 12pt">将当前</span><span style="font-size: 12pt">pack</span><span style="font-size: 12pt">设置压栈保存</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">#pragma pack(2)&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt">必须在结构体定义之前使用</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct S1</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">int i;</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct S3</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c1;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">S1 s;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c2</span></div>
<div style="line-height: 20pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">#pragma pack(pop) // </span><span style="font-size: 12pt">恢复先前的</span><span style="font-size: 12pt">pack</span><span style="font-size: 12pt">设置</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">计算</span><span style="font-size: 12pt">sizeof(S1)</span><span style="font-size: 12pt">时，</span><span style="font-size: 12pt">min(2, sizeof(i))</span><span style="font-size: 12pt">的值为</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">，所以</span><span style="font-size: 12pt">i</span><span style="font-size: 12pt">的偏移量为</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">，加上</span><span style="font-size: 12pt">sizeof(i)</span><span style="font-size: 12pt">等于</span><span style="font-size: 12pt">6</span><span style="font-size: 12pt">，能够被</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">整除，所以整个</span><span style="font-size: 12pt">S1</span><span style="font-size: 12pt">的大小为</span><span style="font-size: 12pt">6</span><span style="font-size: 12pt">。同样，对于</span><span style="font-size: 12pt">sizeof(S3)</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">s</span><span style="font-size: 12pt">的偏移量为</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">，</span><span style="font-size: 12pt">c2</span><span style="font-size: 12pt">的偏移量为</span><span style="font-size: 12pt">8</span><span style="font-size: 12pt">，加上</span><span style="font-size: 12pt">sizeof(c2)</span><span style="font-size: 12pt">等于</span><span style="font-size: 12pt">9</span><span style="font-size: 12pt">，不能被</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">整除，添加一个填充字节，所以</span><span style="font-size: 12pt">sizeof(S3)</span><span style="font-size: 12pt">等于</span><span style="font-size: 12pt">10</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><strong><span style="font-size: 12pt">注意，</span></strong><strong><span style="font-size: 12pt">&ldquo;</span></strong><strong><span style="font-size: 12pt">空结构体</span></strong><strong><span style="font-size: 12pt">&rdquo;</span></strong><strong><span style="font-size: 12pt">（不含数据成员）的大小不为</span></strong><strong><span style="font-size: 12pt">0</span></strong><strong><span style="font-size: 12pt">，而是</span></strong><strong><span style="font-size: 12pt">1</span></strong><strong><span style="font-size: 12pt">。</span></strong></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">8</span></strong><strong><span style="font-size: 14pt">、含位域结构体的</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">前面已经说过，位域成员不能单独被取</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值，我们这里要讨论的是含有位域的结构体的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">，只是考虑到其特殊性而将其专门列了出来。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">C99</span><span style="font-size: 12pt">规定</span><span style="font-size: 12pt">int</span><span style="font-size: 12pt">、</span><span style="font-size: 12pt">unsigned int</span><span style="font-size: 12pt">和</span><span style="font-size: 12pt">bool</span><span style="font-size: 12pt">可以作为位域类型，但编译器几乎都对此作了扩展，允许其它类型类型的存在。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">使用位域的主要目的是压缩存储，其大致规则为：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(1) </span><span style="font-size: 12pt">如果相邻位域字段的类型相同，且其位宽之和小于类型的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">大小，则后面的字段将紧邻前一个字段存储，直到不能容纳为止；</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(2) </span><span style="font-size: 12pt">如果相邻位域字段的类型相同，但其位宽之和大于类型的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">大小，则后面的字段将从新的存储单元开始，其偏移量为其类型大小的整数倍；</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(3) </span><span style="font-size: 12pt">如果相邻的位域字段的类型不同，则各编译器的具体实现有差异，</span><span style="font-size: 12pt">VC6</span><span style="font-size: 12pt">采取不压缩方式，</span><span style="font-size: 12pt">Dev-C++</span><span style="font-size: 12pt">采取压缩方式；</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(4) </span><span style="font-size: 12pt">如果位域字段之间穿插着非位域字段，则不进行压缩；</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">(5) </span><span style="font-size: 12pt">整个结构体的总大小为最宽基本类型成员大小的整数倍。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">示例</span><span style="font-size: 12pt">1</span><span style="font-size: 12pt">：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct BF1</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f1 : 3;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f2 : 4;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f3 : 5;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">位域类型为</span><span style="font-size: 12pt">char</span><span style="font-size: 12pt">，第</span><span style="font-size: 12pt">1</span><span style="font-size: 12pt">个字节仅能容纳下</span><span style="font-size: 12pt">f1</span><span style="font-size: 12pt">和</span><span style="font-size: 12pt">f2</span><span style="font-size: 12pt">，所以</span><span style="font-size: 12pt">f2</span><span style="font-size: 12pt">被压缩到第</span><span style="font-size: 12pt">1</span><span style="font-size: 12pt">个字节中，而</span><span style="font-size: 12pt">f3</span><span style="font-size: 12pt">只能从下一个字节开始。因此</span><span style="font-size: 12pt">sizeof(BF1)</span><span style="font-size: 12pt">的结果为</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">示例</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct BF2</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f1 : 3;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">short f2 : 4;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f3 : 5;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">由于相邻位域类型不同，在</span><span style="font-size: 12pt">VC6</span><span style="font-size: 12pt">中其</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">为</span><span style="font-size: 12pt">6</span><span style="font-size: 12pt">，在</span><span style="font-size: 12pt">Dev-C++</span><span style="font-size: 12pt">中为</span><span style="font-size: 12pt">2</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">示例</span><span style="font-size: 12pt">3</span><span style="font-size: 12pt">：</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct BF3</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f1 : 3;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f2;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f3 : 5;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">非位域字段穿插在其中，不会产生压缩，在</span><span style="font-size: 12pt">VC6</span><span style="font-size: 12pt">和</span><span style="font-size: 12pt">Dev-C++</span><span style="font-size: 12pt">中得到的大小均为</span><span style="font-size: 12pt">3</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt"><strong><span style="font-size: 14pt">9</span></strong><strong><span style="font-size: 14pt">、联合体的</span></strong><strong><span style="font-size: 14pt">sizeof</span></strong></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">结构体在内存组织上是顺序式的，联合体则是重叠式，各成员共享一段内存，所以整个联合体的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">也就是每个成员</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">的最大值。结构体的成员也可以是复合类型，这里，复合类型成员是被作为整体考虑的。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">所以，下面例子中，</span><span style="font-size: 12pt">U</span><span style="font-size: 12pt">的</span><span style="font-size: 12pt">sizeof</span><span style="font-size: 12pt">值等于</span><span style="font-size: 12pt">sizeof(s)</span><span style="font-size: 12pt">。</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">struct S1</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char f1;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">int f2;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char *f3;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">};</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">union U</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">{</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">int i;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">char c;</span></div>
<div style="line-height: 20pt; text-indent: 21pt; margin: 0cm 0cm 0pt 21pt"><span style="font-size: 12pt">S1 s;</span></div>
<div style="line-height: 20pt; text-indent: 21pt"><span style="font-size: 12pt">};&nbsp;&nbsp;</span></div>
</div>]]></description></item></channel></rss>