C/C++数据边界对齐的注意事项

来源:互联网 发布:淘宝拍衣服好看 编辑:程序博客网 时间:2024/06/05 00:24

(我吐槽一下CSDN的编辑器,上面那行老是删不去)

有关C/C++数据边界对齐的基本知识我就不再描述了,可以参考http://blog.csdn.net/dananhai/article/details/1089291,下面我根据我的一些经验简单描述一下数据边界对齐的注意事项。

1.数据对齐的使用

当初弄明白数据边界对齐的原理,并没有思考具体怎么使用,而是为了应付面试。
当建立一个struct或者class,必须考虑其成员变量的数据对齐,来尽可能减少空间的浪费,把占用空间小的元素放在struct/class的前面。例子:

struct align{doubleb;charc;inta;char d;};


以上这个结构体,由于 double b 排在最前面,所以该结构体以double(该结构体中最宽的数据类型)作为数据对齐的方式,double为8个字节的空间,则计算整个结构体的大小时,如果没有达到8的倍数,会自动填充字节到8的倍数。

另外,结构体中的每个数据成员的起始地址,必须是自身数据类型大小的整数倍。拿上面的例子来说,设b的其实地址为0,c的其实地址就为8,但是a的起始地址就不能为9,因为a为int类型,大小为4个字节,编译器会在c后边填充3个字节,使a的其实地址为12。最后,d的起始地址为16。

最后计算总大小:

sizeof(align)
由于8(b的大小)+4(c的大小加上填充的3字节)+4(a的大小)+1(d的大小)=17,17不是8的倍数,编译器会自动填充字节到8的倍数,即24,这时的结果则为24。再来看下面这个结构体:

struct align{charc;char d;inta;doubleb;};


计算字节的方式:1(c的大小)+1(d的大小)+2(字节填充)+4(a的大小)+8(b的大小)=16


用法:把struct/class里的成员变量的大小排个序,按照从小到大的顺序写入结构体内,则能尽可能节省内存空间。

特殊情况:

有的class/struct内的成员变量具有上下文关系,我们可以把相关的成员存储在一起,以便于理解和维护,建议不按照上面的用法来节省内存空间。如:

struct product{intcdrom_amount;doublecdrom_unit_price;intphone_amount;doublephone_unit_price;};

这个结构体,建议按照这种成员排列序列吧,别动手术了。

2.强制数据对齐

应该知道 #pragma pack(2) 的使用:

#pragma pack(2)struct align{charc;inta;doubleb;};#pragma pack()

以上这个结构体强制采用2对齐的方式,则该结构体占用的空间为 2+4+8 = 14。对某个结构体使用强制数据对齐之后,注意恢复数据对齐的方式,即在结构体的最后记得加上:

#pragma pack()

还有要注意的就是不要滥用这个功能,可能会破坏内存的堆栈,或者强制转化的时候发生一些不可预料的情况。慎用。


以上是我总结的,由于表达能力有些欠缺,可能也有我一些理解错误或者理解不透彻的地方,希望大家能指出,望本文能抛砖引玉。



原创粉丝点击