相信大家或多或少都会遇到字节对齐的情况,然而在不明就里的情况下,忽视字节对齐,就会导致数据乱作一团,而不得其解。
这样的问题同样困扰过我,是在跨平台数据交换的时候遇到的。当然,同时还可能会有大小端(Big_Endian and Little_Endian)问题,在此且不谈及。
通过查阅资料,才算略知其一。
默认的字节对齐不一定适用于我们的应用环境,在这样的情景之下,我们需要显示指定字节对齐方式。方法就是预编译指令
“#pragma pack(n)”
需要注意的是这条预编译指令的使用方式,类似于锁的使用,需要成对使用。 在处理完显示指定字节对齐后就要恢复为默认的字节对齐方式,其指令也是#pragma pack()
例如: 以2字节对齐为例
#pragma pack(push)
#pragma pack(2)
#pragma pack(pop)
或者,更简洁一些
#pragma pack(2)
#pragma pack()
另一个相关的问题时,在考虑字节对齐时的类型大小
CASE 1:
#pragma pack(2)
struct A
{
char c; // offsetof(A, c) = 0
double d; // offsetof(A, d) = 2
short s; // offsetof(A, s) = 10
};
#pragma pack()
cout << sizeof(A) << endl; //12
CASE 2:
CASE 1:
#pragma pack(16)
struct A
{
char c; // offsetof(A, c) = 0
double d; // offsetof(A, d) = 8
short s; // offsetof(A, s) = 16
};
#pragma pack()
cout << sizeof(A) << endl; //24
结论:
#pragma pack(n)来设定变量以n字节对齐,就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数; 否则必须为n的倍数。