- 各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
- 每个基本类型有自己默认的对齐方式,通常是这个类型的大小
- 结构体默认的对齐方式是它的所有成员使用的对齐参数中最大的一个
- 结构体的长度必须是所用过的所有对齐参数的整数倍,不够就补空字节。
先来看几个例子
class struct1
{
short a;
long b;
};
struct struct2{
char c;
struct1 s1;
short e;
};
int _tmain(int argc, _TCHAR* argv[])
{
struct2 s2;
cout<<sizeof(struct1)<<endl;
cout<<sizeof(struct2)<<endl;
cout <<((unsigned int)(&s2.s1) - (unsigned int)(&s2))<< endl;
return 0;
}
上面的输出结果是:8 16 4
首先看一下struct1。short的默认大小是2字节,地址从0开始,占据前2个字节;long默认大小是4个字节,起始地址必须4字节对界,前面已经使用2个字节,需要补2个空字节,long占用[4-8]共4个字节。
struct2相对会复杂点。首先第一个字段是char,占用1个字节,没有问题。第二个字段是struct1,问题来了:struct1的对齐字节是多大?根据前面说的第3条规则,struct1的对齐字节是4(long的size>short的size),所以struct1前补3个空字节,struct1占用[4-11]8个字节;第3个字段是short,占用2个字节,且不需要补空字节。struct2到此总共占用了14个字节,但根据前面说的第4条规则:结构体的长度必须是所用过的所有对齐参数的整数倍,不够就补空字节。struct2使用过的对齐参数为1,8,2,最小的公倍数是16,因此struct2实际的size是16个字节。至于第3个表达式就不再解释了。
VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。