vs2005中字节对齐研究

来源:互联网 发布:数据维护是什么工作 编辑:程序博客网 时间:2024/05/22 17:44

一、什么是字节对齐,为什么要对齐?
[本段Quote自]

  现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。

  对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能 从某些特定地址开始存取。比如有些架构的CPU在访问一个没有进行对齐的变量的时候会发生错误,那么在这种架构下编程必须保证字节对齐。其他平台可能没有这种情况,但是最常见的是如果不按照适合其平台要求对 数据存放进行对齐,会在存取效率上带来损失。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。显然在读取效率上下降很多。

二、vs2005中字节对齐研究

2.1 默认对齐值

字节对齐一般体现在struct结构类型中,这就是我们sizeof一个结构类型常常得到与预想结果不同的原因。

struct A
{
  char achar;   //1B
  short int ashort; //2B
  long int along;  //4B
};
结构体A实际占用的空间是7B,可是我们使用sizeof(A)会发现其值为8。跟踪调试会发现地址分配如下(图1):

  我们发现char的起始地址%1=0,short的起始地址%2=0,long的地址%4=0,也就是说,每种变量的起始地址为其类型占用空间的整数倍,这个值,称为类型的自身对齐值

  为了验证以上说法,我们将结构体的变量顺序调整一下,将long类型提前,如图2所示,跟踪调试发现仍然符合上述规律。此时,原本占1B空间的char变量占用了4B的空间,这是因为出于对齐需要,long变量需要存在%4=0的起始地址上。

  那为什么图1中sizeof值为8,图2的sizeof值不是10而是12呢?这是因为结构体默认按照最大类型的对齐值对齐,即,结构体的sizeof值为最大类型的sizeof值的整数倍。因此图2中的sizeof值不是10而是12,最后一个变量short占用了4B的空间。

  作为上述说法的依据,我们看图3。该结构体里面最大类型为short,大小为2B,因此sizeof值为6,只需要是2的整数倍。
图3

  从图4中,我们可以验证,char类型只需要存储在%1=0的地址上,也就是可以任意存取。
图4

2.2 设置指定对齐值

  可以使用预编译指令#pragma pack(对齐字节数)来指定对齐的字节数。如图5所示。

图5

  对比图2和图5,由于使用了#pragma pack(2)命令,因此long变量的起始地址不再是%4=0,而是%2=0,而sizeof的值也不再是最大类型long(4B)的倍数,而是2的倍数10。

  那当指定对齐值比数据类型自身对齐值大的时候,是什么情况呢?见图6:
图6

  可以看出当指定对齐值为2的时候,char仍旧是按其自身对齐值对齐的,即地址为%1=0。因此最终对齐值等于自身对齐值和指定对齐值中的较小值。图7验证了这个说法。当结构体中都是char类型的时候,即使指定pack(2),结构体的sizeof值仍旧可以不是2的整数倍。

图7

2.3 小结

1、“对齐”有两个含义,一是数据存放的起始地址必须是%N=0,二是struct的sizeof值会是N的整数倍;
2、基本数据类型的“自身对齐值”是指其类型占用的空间大小;
3、使用预编译命令#pragma pack(字节数)可以指定对齐字节数;使用#pragma pack()可以恢复缺省对齐;
4、当数据类型的自身对齐值与指定对齐值不一致时,最终对齐值为两者中的较小值。


转至:http://hi.baidu.com/czlaner/item/7135c3156a7e99ce39cb309a


原创粉丝点击