#include<iostream.h>
void main()
{
struct A
{
short a;
int b;
double c;
char d[6];
};
A test;
test.a=1;
test.b=2;
test.c=3.0;
cout<<sizeof(struct A)<<endl;
cout<<&test<<endl;
cout<<&test.a<<endl;
cout<<&test.b<<endl;
cout<<&test.c<<endl;
cout<<&test.d<<endl;
}
输出为:
24
0x0012FF68
0x0012FF68
0x0012FF6C
0x0012FF70
0x0012FF78
Press any key to continue
从输出的成员地址可以推断出:short类型需要2字节对齐,int类型需要4字节对齐,double类型需要8字节对齐,相对于结构体的起始地址,成员a的起始偏移为0,占用2个字节,成员b的起始偏移为4字节,占用4个字节(可以知道a和b中有多余的两个字节,未被使用,为了对齐操作而空出来的),成员c的起始偏移为8,占用8的字节,成员d起始偏移在8+8的位置,大小为占用了6个字节,猜测结构体大小应该是:
2+填充了的2字节+4+8+6=22.
这里结果输出确为24,推断其原因是和结构体中最占用字节的成员有关,结构体大小需要按这个成员的对齐方式对齐。如这里最占用字节的成员为double,对齐方式是8字节对齐,所以结构体也需要8字节对齐,所以22向上取到8字节对齐位置,是24.
下面的一系列实验来验证上述推断:
#include<iostream.h>
void main()
{
struct A
{
short a;
int b;
char c[4];
};
A test;
test.a=1;
test.b=2;
cout<<sizeof(struct A)<<endl;
cout<<&test<<endl;
cout<<&test.a<<endl;
cout<<&test.b<<endl;
cout<<&test.c<<endl;
}
输出为:
12
0x0012FF74
0x0012FF74
0x0012FF78
0x0012FF7C
Press any key to continue
结构体对齐方式为最大成员的对齐方式,这里是4字节对齐,结构体大小为:
2+2字节填充+4=4=12. 12已经4字节对齐了不需要填充
#include<iostream.h>
void main()
{
struct A
{
short a;
int b;
char c[5];
};
A test;
test.a=1;
test.b=2;
cout<<sizeof(struct A)<<endl;
cout<<&test<<endl;
cout<<&test.a<<endl;
cout<<&test.b<<endl;
cout<<&test.c<<endl;
}
相同的代码,只是成员c为5个字节,这时候输出为:
16
0x0012FF70
0x0012FF70
0x0012FF74
0x0012FF78
Press any key to continue
用上述推论进行解释:结构体对齐方式为最大成员的对齐方式,这里是4,结构体大小计算为:
2+2填充字节+4+5=13,13没有4字节对齐,所以还会在后面填充3个字节,使得结构体大小为16.
将结构体的成员的顺序进行调换,会影响结构体的大小,原因在于内存对齐的问题,读者可以根绝我的小小的推论自行分析。主要是结构体成员自己有对齐问题,结构本身也需要对齐,对齐方式与最大对齐方式的成员一致