天天看点

字节对齐

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

       内存对齐是为了提高CPU对数据的访问速度(特别是在栈中)。对于对齐的内存地址,处理器仅需一次就可以访问到,而对于未对齐的内存地址,处理器需要访问两次。

       我们写程序时不需要去指定对齐方式,编译器会去自动对齐,同样,我们可以自己指定对齐值。由于编译器有自动对齐的机制,所以一般我们是不需要考虑对齐的。对于内存对齐问题,最常见的就是struct结构体的sizeof的结果。下面通过例子介绍一下内存对齐问题。

       char类型占一个字节,所以起始的偏移地址按1对齐(即起始偏移地址%1=0);int类型占四个字节,所以起始偏移地址按4对齐(即起始偏移地址%4=0);short类型占2个字节,所以起始偏移地址%2=0);double占8个字节,所以起始偏移地址按8对齐(即起始偏移地址%8=0);同时,结构体自身也要考虑对齐,即结构体所占空间总和为这个对齐值的整数倍。

       (偏移地址%N=0,其中N取自身对齐值和指定对齐值里较小的值,VC6默认对齐值为8。以上几个对齐值是各个类型数据的自身对齐值。而结构体的对齐值为结构体成员里对齐值得最大值和指定对齐值两者里取较小值)

       假设地址是从0x1000开始的,char类型对齐值为1,0x1000%1=0,所以存放地址符合要求;int类型的对齐值为4,所以起始地址要从0x1004开始到0x1007这四个字节来存放,0x1004%4=0;short对齐值为2,起始地址0x1008%2=0,符合要求;再考虑结构体自身的对齐值,结构体自身的对齐值为4,0x1000~0x1009为10B,12%4=0,所以0x100A和0x100B也为这个结构体所占用,总共12个字节,因此,sizeof(test1)=12。

       同理,下面的例子sizeof的结果分别为8和12.

struct test2 

    char a; 

    char b; 

    int c; 

}; 

       如果需要人工指定对齐值,则使用以下命令:

       #pragma pack(val);      /*val为对齐值,VC6默认8字节对齐*/

       #pragma pack();         /*取消指定对齐值,恢复默认对齐值*/

继续阅读