|
|
发表于 2008-2-18 21:09:00
|
显示全部楼层
Re:结构成员对齐(Structure Padding)具体是怎么做的
默认的是以结构自身的大小对齐的, 成员x的偏移只可能是sizeof(x)的倍数
且结构的大小为成员中最大成员的倍数,比如:
struct s0 { char a; char b; char c; };
各自都以1字节对齐,sizeof(s0) = 3
struct s1 { char a; int b; };
中 a 的偏移是0
b的大小为4字节,会以4字节对齐,所以b的偏移是4
sizeof(s1) = 8, 也就是说结构的第一字节是 a, 第2到4字节未使用,5到8字节是b
struct s2 { char a; char b; int c; short d; short e; __int64 f; int g; };
成员 大小 偏移
a 1 0
b 1 1
c 4 4
d 2 8
e 2 10
f 8 16
g 4 24
结构的大小似乎应该是 24+sizeof(g) = 24+4 = 28
但是结构中最大的成员是 __int64(8字节),所以整个结构大小是 32 字节,为最大成员大小8的4倍
另外数组的偏移是连续的,比如
struct s3 { char a; int b; short c[17]; };
成员 偏移
a 0
b 4
c[0] 8
c[1] 10
... ...
c[15] 38
c[16] 40
结构的大小不是42字节而是44字节,要补齐最大成员int b(4字节)的整数倍
还有指针的问题,指针的大小全部是一样的,x86的程序指针为4字节,x64的程序指针全部为8字节
struct s4 { int a; short* b; };
比如这个结构编译为32位,sizeof(s4) = 8
成员 偏移 大小
a 0 4
b 4 4
编译为64位程序,sizeof(s4) = 16
成员 偏移 大小
a 0 4
b 8 8
需要改变对其方式可以使用 #pragma
比如
#pragma pack (1) // 按1字节对齐
struct s5 { char a; int b; }
#pragma pack () // 恢复默认
那么 sizeof(s5) = 5,a的偏移为0,b为1
还可以使用
#pragma pack (push) // 保存当前对齐方式
#pragma pack (n) // 按 n 字节对齐, n只能为1, 2, 4, 8, 16
#pragma pack (pop) // 恢复对齐方式
也可以单独用在某个成员上
struct s6
{
char a;
#pragma pack (1) // 按1字节对齐
int b;
#pragma pack ()
short c[17];
};
a偏移0
b偏移1
c[0]偏移6 (不是5),c[0]是要按照 sizeof(c[0])对齐的,c[1]之后的不需要对齐
c[16]偏移38
d偏移40
而原来最大的成员b按1字节对齐,所以按除此之外剩下最大成员c[0]的大小补齐
结构是42(最后补上了1字节),补齐c[0]的整数倍
还有一个关键字可以控制对齐
比如
__declspec( align(32) ) struct s7
{
int a;
__declspec( align(8) ) char b;
__declspec( align(4) ) char c;
};
这样结构本身以32字节对齐,也就是说sizeof(s7)=32
其中b会以8字节对齐,c按4字节对齐
b的偏移为8,c为12
s7 x[2];
这样的数组,x[1] 和 x[0] 的地址相差32字节
最后,这个方法可以取得成员的偏移
struct s8
{
short a;
int b;
};
int offsetA = (int) &((s8*)0)->a;
int offsetB = (int) &((s8*)0)->b;
呵呵,明白否?希望对你有帮助。 [em13] |
|