<p class="MsoNormal"><span>我们先看一道</span>
<span>IBM</span>
<span>和微软的笔试题:</span>
</p>
<p class="MsoNormal"><span>IBM</span>
<span>笔试题:</span>
</p>
<p class="MsoNormal"><span>struct{ </span>
</p>
<p class="MsoNormal"><span> short a1;</span>
</p>
<p class="MsoNormal" style="text-indent: 12pt;"><span>short a2;</span>
</p>
<p class="MsoNormal"><span> short a3;</span>
</p>
<p class="MsoNormal"><span> }A;</span>
</p>
<p class="MsoNormal"><span> struct{ </span>
</p>
<p class="MsoNormal"><span> long a1;</span>
</p>
<p class="MsoNormal"><span> short a2; </span>
</p>
<p class="MsoNormal"><span> }B; </span>
</p>
<p class="MsoNormal"><span> sizeof( A)=6, sizeof(B)=8,</span>
<span>为什么?</span>
<span> </span>
</p>
<p class="MsoNormal"><span> </span>
<span>注:</span>
<span>sizeof(short)=2,sizeof(long)=4</span>
</p>
<p class="MsoNormal"><span> </span>
</p>
<p class="MsoNormal"><span>微软笔试题:</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">struct example1</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
{</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
short a ;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
long b;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
};</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"> </span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
struct example2</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
{</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
char c;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
example1 struct1;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
short e;<span> </span>
</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
};</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"> </span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">int main(int argc, char* argv[])</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">{</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"> example1 e1;<br></span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
example2 e2;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
int d=(unsigned int)&e2.struct1-(unsigned int)&e2.c;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
printf("%d,%d,%d/n",sizeof(e1),sizeof(e2),d);</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
return 0;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">}</span>
</p>
<p class="MsoNormal"><span>输出结果?</span>
</p>
<p class="MsoNormal"><span> </span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>要能清除的分析上面的问题就要搞清楚结构体变量的成员在内存里是如何分布的、成员先后顺序是怎样的、成员之间是连续的还是分散的、还是其他的什么形式?其实这些问题既和软件相关又和硬件相关。所谓软件相关主要是指和具体的编程语言的编译器的特性相关,编译器为了优化</span>
<span>CPU</span>
<span>访问内存的效率,在生成结构体成员的起始地址时遵循着某种特定的规则,这就是所谓的</span>
<span> </span>
<strong><span>结构体成员“对齐”;</span>
</strong>
<span>所谓硬件相关主要是指</span>
<span>CPU</span>
<span>的“字节序”问题,也就是大于一个字节类型的数据如</span>
<span>int</span>
<span>类型、</span>
<span>short</span>
<span>类型等,在内存中的存放顺序,即单个字节与高低地址的对应关系。字节序分为两类:</span>
<span>Big-Endian</span>
<span>和</span>
<span>Little-Endian</span>
<span>,有的文章上称之为“大端”和“小端”,他们是这样定义的:</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>Little-Endian</span>
<span>就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端;</span>
<span>Big-Endian</span>
<span>就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>Intel</span>
<span>、<span>VAX</span>
和<span>Unisys</span>
处理器的计算机中的数据的字节顺序是</span>
<span>Little-Endian</span>
<span>,</span>
<span>IBM </span>
<span>大型机和大多数<span>Unix</span>
平台的计算机中字节顺序是</span>
<span>Big –Endian</span>
<span>。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>关与</span>
<span>Big-Endian</span>
<span>和</span>
<span>Little-Endian</span>
<span>问题本文暂不做详细讨论,本文将以小端机(此处为</span>
<span>intel x86</span>
<span>架构的计算机)、</span>
<span>OS</span>
<span>:</span>
<span>WindowsXp</span>
<span>和</span>
<span>VC++6.0</span>
<span>编译器来详细讨论结构体成员的“对齐”问题。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>前面说了</span>
<span>,</span>
<span>为了优化</span>
<span>CPU</span>
<span>访问内存的效率,程序语言的编译器在做变量的存储分配时就进行了分配优化处理,优化规则大致原则是这样</span>
<span>: </span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span> </span>
<span>对于</span>
<span>n</span>
<span>字节的元素</span>
<span>(n=2,4,8,...)</span>
<span>,它的首地址能被</span>
<span>n</span>
<span>整除,这种原则称为“<strong>对齐</strong>
”,如</span>
<span>WORD(2</span>
<span>字节</span>
<span>)</span>
<span>的值应该能被</span>
<span>2</span>
<span>整除的位置,</span>
<span>DWORD</span>
<span>(</span>
<span>4</span>
<span>字节)应该在能被</span>
<span>4</span>
<span>整除的位置。</span>
<span> </span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>对于结构体来说,结构体的成员在内存中顺序存放,所占内存地址依次增高,第一个成员处于低地址处,最后一个成员处于最高地址处,但结构体成员的内存分配不一定是连续的,编译器会对其成员变量依据前面介绍的</span>
<span> </span>
<span>“对齐”原则进行处理。对待每个成员类似于对待单个</span>
<span>n</span>
<span>字节的元素一样,依次为每个元素找一个适合的首地址,使得其符合上述的“对齐”原则。通常编译器中可以设置一个对齐参数</span>
<span>n</span>
<span>,但这个</span>
<span>n</span>
<span>并不是结构体成员实际的对齐参数,</span>
<span>VC++6.0</span>
<span>中结构体的每个成员实际对齐参数</span>
<span>N</span>
<span>通常是这样计算得到的</span>
<span>N</span>
<em><span style="font-size: 10pt;">=</span>
</em>
<span>min(sizeof(</span>
<span>该成员类型</span>
<span>)</span>
<span>,</span>
<span>n)</span>
<span>(</span>
<span>n</span>
<span>为</span>
<span>VC++6.0</span>
<span>中可设置的值)。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>成员的内存分配规律是这样的:<strong>从结构体的首地址开始向后依次为每个成员寻找第一个满足条件的首地址</strong>
</span>
<strong><span>x</span>
</strong>
<strong><span>,该条件是</span>
</strong>
<strong><span>x</span>
</strong>
<strong><span style="font-size: 10pt;"> <span>%</span>
</span>
</strong>
<strong><span>N</span>
</strong>
<strong><span style="font-size: 10pt;"> <span>=</span>
0</span>
</strong>
<strong><span style="font-size: 10pt;">,</span>
</strong>
<strong><span>并且整个结构的长度必须为各个成员所使用的对齐参数中最大的那个值的最小整数倍</span>
</strong>
<strong><span>,</span>
</strong>
<strong><span>不够就补空字节</span>
</strong>
<span>。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>结构体中所有成员的对齐参数</span>
<span>N</span>
<span>的最大值称为<strong>结构体的对齐参数</strong>
。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>VC++6.0</span>
<span>中</span>
<span>n</span>
<span style="font-size: 12pt;"> </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;">C/C++</span>
<span style="font-size: 12pt;">”选项卡的“分类”中</span>
<span style="font-size: 12pt;"> </span>
<span style="font-size: 12pt;">“</span>
<span style="font-size: 12pt;">Code Generation </span>
<span style="font-size: 12pt;">”的“</span>
<span style="font-size: 12pt;">Struct member alignment</span>
<span style="font-size: 12pt;">”</span>
<span style="font-size: 12pt;"> </span>
<span style="font-size: 12pt;">中设置,</span>
<span style="font-size: 12pt;">1byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">2byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">4byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">8byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">16byte</span>
<span style="font-size: 12pt;">等几种,默认为</span>
<span style="font-size: 12pt;">8byte</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 12pt;"><a href="http://jisuanji.xawl.org/Data/Working/1EC27F05-1E24-4293-943E-E45DE41CF198.htm">http://jisuanji.xawl.org/Data/Working/1EC27F05-1E24-4293-943E-E45DE41CF198.htm</a>
</span>
</p>
<span>IBM</span>
<span>和微软的笔试题:</span>
</p>
<p class="MsoNormal"><span>IBM</span>
<span>笔试题:</span>
</p>
<p class="MsoNormal"><span>struct{ </span>
</p>
<p class="MsoNormal"><span> short a1;</span>
</p>
<p class="MsoNormal" style="text-indent: 12pt;"><span>short a2;</span>
</p>
<p class="MsoNormal"><span> short a3;</span>
</p>
<p class="MsoNormal"><span> }A;</span>
</p>
<p class="MsoNormal"><span> struct{ </span>
</p>
<p class="MsoNormal"><span> long a1;</span>
</p>
<p class="MsoNormal"><span> short a2; </span>
</p>
<p class="MsoNormal"><span> }B; </span>
</p>
<p class="MsoNormal"><span> sizeof( A)=6, sizeof(B)=8,</span>
<span>为什么?</span>
<span> </span>
</p>
<p class="MsoNormal"><span> </span>
<span>注:</span>
<span>sizeof(short)=2,sizeof(long)=4</span>
</p>
<p class="MsoNormal"><span> </span>
</p>
<p class="MsoNormal"><span>微软笔试题:</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">struct example1</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
{</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
short a ;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
long b;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
};</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"> </span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
struct example2</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
{</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
char c;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
example1 struct1;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
short e;<span> </span>
</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
};</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"> </span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">int main(int argc, char* argv[])</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">{</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"> example1 e1;<br></span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
example2 e2;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
int d=(unsigned int)&e2.struct1-(unsigned int)&e2.c;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
printf("%d,%d,%d/n",sizeof(e1),sizeof(e2),d);</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;"><span> </span>
return 0;</span>
</p>
<p class="MsoNormal"><span style="font-size: 12pt;">}</span>
</p>
<p class="MsoNormal"><span>输出结果?</span>
</p>
<p class="MsoNormal"><span> </span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>要能清除的分析上面的问题就要搞清楚结构体变量的成员在内存里是如何分布的、成员先后顺序是怎样的、成员之间是连续的还是分散的、还是其他的什么形式?其实这些问题既和软件相关又和硬件相关。所谓软件相关主要是指和具体的编程语言的编译器的特性相关,编译器为了优化</span>
<span>CPU</span>
<span>访问内存的效率,在生成结构体成员的起始地址时遵循着某种特定的规则,这就是所谓的</span>
<span> </span>
<strong><span>结构体成员“对齐”;</span>
</strong>
<span>所谓硬件相关主要是指</span>
<span>CPU</span>
<span>的“字节序”问题,也就是大于一个字节类型的数据如</span>
<span>int</span>
<span>类型、</span>
<span>short</span>
<span>类型等,在内存中的存放顺序,即单个字节与高低地址的对应关系。字节序分为两类:</span>
<span>Big-Endian</span>
<span>和</span>
<span>Little-Endian</span>
<span>,有的文章上称之为“大端”和“小端”,他们是这样定义的:</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>Little-Endian</span>
<span>就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端;</span>
<span>Big-Endian</span>
<span>就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>Intel</span>
<span>、<span>VAX</span>
和<span>Unisys</span>
处理器的计算机中的数据的字节顺序是</span>
<span>Little-Endian</span>
<span>,</span>
<span>IBM </span>
<span>大型机和大多数<span>Unix</span>
平台的计算机中字节顺序是</span>
<span>Big –Endian</span>
<span>。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>关与</span>
<span>Big-Endian</span>
<span>和</span>
<span>Little-Endian</span>
<span>问题本文暂不做详细讨论,本文将以小端机(此处为</span>
<span>intel x86</span>
<span>架构的计算机)、</span>
<span>OS</span>
<span>:</span>
<span>WindowsXp</span>
<span>和</span>
<span>VC++6.0</span>
<span>编译器来详细讨论结构体成员的“对齐”问题。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>前面说了</span>
<span>,</span>
<span>为了优化</span>
<span>CPU</span>
<span>访问内存的效率,程序语言的编译器在做变量的存储分配时就进行了分配优化处理,优化规则大致原则是这样</span>
<span>: </span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span> </span>
<span>对于</span>
<span>n</span>
<span>字节的元素</span>
<span>(n=2,4,8,...)</span>
<span>,它的首地址能被</span>
<span>n</span>
<span>整除,这种原则称为“<strong>对齐</strong>
”,如</span>
<span>WORD(2</span>
<span>字节</span>
<span>)</span>
<span>的值应该能被</span>
<span>2</span>
<span>整除的位置,</span>
<span>DWORD</span>
<span>(</span>
<span>4</span>
<span>字节)应该在能被</span>
<span>4</span>
<span>整除的位置。</span>
<span> </span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>对于结构体来说,结构体的成员在内存中顺序存放,所占内存地址依次增高,第一个成员处于低地址处,最后一个成员处于最高地址处,但结构体成员的内存分配不一定是连续的,编译器会对其成员变量依据前面介绍的</span>
<span> </span>
<span>“对齐”原则进行处理。对待每个成员类似于对待单个</span>
<span>n</span>
<span>字节的元素一样,依次为每个元素找一个适合的首地址,使得其符合上述的“对齐”原则。通常编译器中可以设置一个对齐参数</span>
<span>n</span>
<span>,但这个</span>
<span>n</span>
<span>并不是结构体成员实际的对齐参数,</span>
<span>VC++6.0</span>
<span>中结构体的每个成员实际对齐参数</span>
<span>N</span>
<span>通常是这样计算得到的</span>
<span>N</span>
<em><span style="font-size: 10pt;">=</span>
</em>
<span>min(sizeof(</span>
<span>该成员类型</span>
<span>)</span>
<span>,</span>
<span>n)</span>
<span>(</span>
<span>n</span>
<span>为</span>
<span>VC++6.0</span>
<span>中可设置的值)。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>成员的内存分配规律是这样的:<strong>从结构体的首地址开始向后依次为每个成员寻找第一个满足条件的首地址</strong>
</span>
<strong><span>x</span>
</strong>
<strong><span>,该条件是</span>
</strong>
<strong><span>x</span>
</strong>
<strong><span style="font-size: 10pt;"> <span>%</span>
</span>
</strong>
<strong><span>N</span>
</strong>
<strong><span style="font-size: 10pt;"> <span>=</span>
0</span>
</strong>
<strong><span style="font-size: 10pt;">,</span>
</strong>
<strong><span>并且整个结构的长度必须为各个成员所使用的对齐参数中最大的那个值的最小整数倍</span>
</strong>
<strong><span>,</span>
</strong>
<strong><span>不够就补空字节</span>
</strong>
<span>。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>结构体中所有成员的对齐参数</span>
<span>N</span>
<span>的最大值称为<strong>结构体的对齐参数</strong>
。</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span>VC++6.0</span>
<span>中</span>
<span>n</span>
<span style="font-size: 12pt;"> </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;">C/C++</span>
<span style="font-size: 12pt;">”选项卡的“分类”中</span>
<span style="font-size: 12pt;"> </span>
<span style="font-size: 12pt;">“</span>
<span style="font-size: 12pt;">Code Generation </span>
<span style="font-size: 12pt;">”的“</span>
<span style="font-size: 12pt;">Struct member alignment</span>
<span style="font-size: 12pt;">”</span>
<span style="font-size: 12pt;"> </span>
<span style="font-size: 12pt;">中设置,</span>
<span style="font-size: 12pt;">1byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">2byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">4byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">8byte</span>
<span style="font-size: 12pt;">、</span>
<span style="font-size: 12pt;">16byte</span>
<span style="font-size: 12pt;">等几种,默认为</span>
<span style="font-size: 12pt;">8byte</span>
</p>
<p class="MsoNormal" style="text-indent: 21pt;"><span style="font-size: 12pt;"><a href="http://jisuanji.xawl.org/Data/Working/1EC27F05-1E24-4293-943E-E45DE41CF198.htm">http://jisuanji.xawl.org/Data/Working/1EC27F05-1E24-4293-943E-E45DE41CF198.htm</a>
</span>
</p>