字节对齐

来源:互联网 发布:建筑网络计划图 编辑:程序博客网 时间:2024/06/05 13:32

 字节对齐的意义:

字节对齐是计算机系统的存储器与处理器数据交换规则。数据在存储器上存储方式决定了处理器的读取速度,对齐限制为双方制定了一个约定,简化了双方的硬件接口设计。

假如处理器一次从存储器中取4个字节,处理器每次都会在地址为4K(4的整数倍)的地址开始读取数据。

举个例子:

struct T1{    char c;    short s;    int i;}

sizeof(T1)结果是8字节,数据在内存中的分布如下:


如果没有字节对齐的话,需要把变量s和i前移一个字节,


而目前处理器是以4字节为单位从存储器中读取数据,后果就是读取变量i时需要读两次内存,因为变量i分布在0-3和4-7两个单元上,

这是计算机在空间和时间的博弈,损失空间换取时间。


一个结构体在内存中占多少字节?

按照字节对齐的原则,K字节的对象的地址必须是nK,结构体中的变量按照顺序,依次找到符合自己的位置(short要求2k,int要求4k,double要求8k。。。),中间没有用到的字节使用占位符,也要算到结构体的长度中。

在这里需要解释windows严格要求k字节对象的地址必须是k的倍数,linux在处理8字节的double变量时,采用了4字节对齐。


————————————————————————————————————————————————————————————————————————

除了系统提供的规则,我们可以在自己的程序制定字节对齐规则。

使用预编译指令#pragma pack (value)告诉编译器对齐数value,如下

#pragma pack(4)struct T2{short s;int i;}#pragma pack()


按照4字节对齐之后,结构体大小为8字节,结构体在内存分布如下:



#pragma pack(2)struct T3{short s;int i;}#pragma pack()

按照2字节对齐之后,结构体大小变为6字节,结构体在内存中分布如下:

需要注意的是对齐规则只对 value>sizeof(成员)的结构体成员生效,例如pack(4)并不会改变short成员存储在2K地址的规则,但是double就会从4K的地址开始存放。

使用#pragma pack编译选项应该清楚的意识到,它会为程序带来什么影响。

如果pack(1),那么结构体会依次排布占满所有的地址,这样做的好处是使用最小的地址空间,但是这样处理器在读取结构体时效率最低。

字节对齐方式与处理器地址宽度相同,这时处理器读取结构体效率最高,吞吐率也最大。

————————————————————————————————————————————————————————————————————————

一些建议:

1.定义结构体时,按照变量占用空间的大小,由大到小确定结构体中变量的顺序,这样可以既节省空间,又不损失效率。

2.网络中传递数据时,最好双方约定字节对齐方式,因为不同系统之间的字节对齐方式有可能不同。

3.当结构体中嵌套结构体时,最好不要让内存结构体把外层结构体分隔开,这样的话外层结构体字节对齐方式会被分为两种。