分享

struct的内存对齐(转)

 戴维图书馆 2013-12-17

结构体的对齐

sizeof计算一个结构体的大小时,经常得到的值比结构体内部成员所占内存总和要大,这就是因为在结构体内部,成员在存储时有对齐的规则。结构体对齐指的是 编译器向结构体插入无用内存的能力,插入无用内存使得结构体成员以最佳方式对齐,从而得到更高的效能。当基本数据类型以字节地址(几倍于自身大小)存储时,很多处理器能够获得最佳效能。

以下是几个例子:

Struct x

{

Short s;//2 bytes and 2 padding tytes

Int i; //4 bytes

Char c; //1 bytes and 3 padding bytes

};

Struct y

{

Int i; //4 bytes

Char c ; //1 bytes and 1 padding byte

Short s; //2 bytes

};

Struct z

{

Int i; //4 bytes

Short s; // 2 bytes

Char c; //1 bytes and 1 padding byte

};

Sizeof(x)=12; sizeof(y)=8; sizeof(z)=8;

X的内存布局: s I c

11** 1111 1***

Y的内存布局: I c s

1111 1* 11

Z的内存布局: I s c

1111 11 1*

其中*表示填充的字节,xs后面为什么 要填充两个 字节?因为i是整型,其起始位置要为4的倍数。C后面要填充3个字节,因为结构体size要为4(即最大类型 ——整型sizeof(int))的倍数。

YC后面填充一个 字节,因为sshort类型,起始位置要为2的倍数。S后面没有填充,因为cs正好占用 4个字节。

Zs后面没有填充,因为sc正好占用4个字节,c填充一个字节 因为struct大小要为int的整数倍。

再看一个有结构体作为成员的例子:

Struct A

{

Int a;

Double b;

Float c;

};

Struct B

{

Char e[2];

Int f;

Double g;

Short h;

Struct A I;

};

Sizeof(A)=24; 因为 int4double8float4,总长为8 倍数,补齐,所以为24 Sizeof(B)=48;看一下B的布局

B的内存布局:e f g h i

11** 1111 11111111 11****** 1111****, 11111111, 1111****

I其实就是A的内存布局。I 起始位置要为24的倍数,所以h后面要补齐(A的最大类型是double,占8个字节,所以i开始要8字节对齐,即8的倍数,所以h要填充)。

通过把最大的数据类型放在结构体的开始,最小数据类型放在结构体的最后,这样可以得到最小的结构体size

通过上面的例子可以总结一下三个规律:

1 数据成员对齐,结构体(或联合体)的数据成员,第一个数据成员放在offset0的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开始(比如int32位机为4字节,则要从4的整数倍地址开始存储)。

2 结构体作为成员,如果 一个 结构体里面有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储(struct b里面有struct aa里面有charintdouble等元素,那么a应该从8的整数倍开始存储)。

3 结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

还有一种常见情况,结构体中含有位域字段。位域成员不能单独被取sizeof值。规定intunsigned int bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其他类型的存在。使用位于的主要目的是压缩存储,其大致规则:

1 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的 字段将紧邻前一个字段存储,知道不能容纳为止;

2 如果相邻字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;

3 如果相邻的位域字段的类型 不同,则各编译器的 具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;

4 如果位域字段之间穿插着非位域字段,则不进行压缩。

5 整个结构体的总大小为最宽基本类型成员大小的整数倍。

看下面例子:

struct A{

short f1:3;

short f2:4;

short f3:10;

}; A的布局为 f 1 f2 f3

111 1111*** **(11*) 1—1(101)**(6*) 位域类型为short,第一个字节能容纳f1f2,所以f2被压缩到第1个字节中,而f3只能从下一个字节开始。因此sizeof(A)=2

Struct B{

Char f1:3;

Short f2:4;

Char f3:5;

};相邻位域的类型不同,在VC6sizeof6,在Dev-C++中为2.

Struct C{

Char f1:3;

Char f2;

Char f3:5;

};非位域字段插在其中,不会产生压缩,大小为3

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多