2008年3月3日星期一

#pragma pack控制下的内存数据对齐

struct或类是复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
自然对界是指按结构体的成员中 sizeof 最大的成员对齐。
#pragma pack规定的对齐长度,实际使用的规则是:结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和结构体的自然对齐长度中比较小的那个进行。就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。整个结构体的对齐,按照结构体中size最大的数据成员和#pragma pack指定值之间,较小的那个进行。
具体解释:
#pragma pack(4)
class TestB
{
public:
int aa; //第一个成员,放在[0,3]偏移的位置
char a; //第二个成员,自身长为1,#pragma pack(4), 取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。    
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。    
char c; //第四个,自身长为1,放在[8]的位置。
};
这个类实际占据的内存空间是9字节类之间的对齐,是按照类内部最大的成员的长度,和#pragma pack规定的值之中较小的一个对齐的。所以这个例子中,类之间对齐的长度是min(sizeof(int),4),也就是4。9按照4字节圆整的结果是12,所以sizeof(TestB)是12。
如果
#pragma pack(2)
class TestB
{
public:
int aa; //第一个成员,放在[0,3]偏移的位置,
char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。    
short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。    
char c; //第四个,自身长为1,放在[8]的位置。  
};
//可以看出,上面的位置完全没有变化,只是类之间改为按2字节对齐,9按2圆整的结果是10。
//所以 sizeof(TestB)是10。
使用伪指令#pragma pack (),取消自定义字节对齐方式。
#pragma pack(push, 1)与#pragma pack(1)作用一样
#pragma pack(pop)和#pragma pack()作用一样

标签:


评论: 发表评论

订阅 博文评论 [Atom]





<< 主页

This page is powered by Blogger. Isn't yours?

订阅 博文 [Atom]