C/C++中关于struct和union的内存对齐原则

时间:2022-09-05 11:50:53

在sizeof计算一个结构体的大小时,经常得到的值比结构体内部成员所占内存总和要大,这就是因为在结构体内部,成员在存储时有对齐的规则。

     对齐原则一般满足以下几点:

1.结构体第一个数据成员放在offset为0的地方,后面每个成员相对于结构体首地址的偏移量(offset)都是成员大小(该变量类型所占字节)的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);

2.如果一个结构里有某些结构体成员,则结构体成员要从其内部"最宽基本类型成员"的整数倍地址开始存储(struct a里存有struct b,b里有char 、int 、double等元素,那b应该从8的整数倍开始存储);

3.结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的"最宽基本类型成员"的整数倍。

注:union和struct计算方法不太一致,可以看下面讲解。

例子:

union u1
{
double a;
int b;
};
union u2
{
char a[13];
int b;
};
union u3
{
char a[13];
char b;
};

cout<<sizeof(u1)<<endl;//8
cout<<sizeof(u2)<<endl;//16
cout<<sizeof(u3)<<endl;//13

union联合体其大小取决于所有成员中,占用空间最大的一个成员的大小。

我们可以看到u1中最大的成员是double型所以占用8字节。但是u2和u3为什么分别是16和13呢?u2中int类型为最大,使u2的对齐方式变为4,也就是说,u2的大小必须在4的对界上,所以占用的空间变成了16(最接近13的对界)。而u3中都是char,所以sizeof(u3)为13。

例子:

struct s1
{
 short a;//2 bytes and 2 padding bytes
 int i;//4 bytes
 char c; //1 byte and 3 padding bytes
};

struct s2
{
 int i;//4 bytes
 char c;//1 byte and 1 padding byte
 short a;//2 bytes
};

struct s3
{
 int i;//4 bytes
 char c;// 1 byte and 1 padding byte
 short a;//2 bytes
double d;//8 bytes
};
cout<<sizeof(s1)<<endl; // 12
cout<<sizeof(s2)<<endl; // 8
cout<<sizeof(s3)<<endl;//16

s1的内存布局:

a

11**

i

1111

c

1***

s2的内存布局:

i

1111

c   a

1* 11

s3的内存布局:

i        c   a

1111 1* 11

d

11111111

这里“*” 指代的是填充的字节,原来类型每占几个字节就用几个“1”表示。按照以上原则我们可以看到s1和s2区别,s1中的变量i 不能紧接着变量a进行存放,因为紧着i 的偏移量为2,不是int类型 4的倍数,所以要另外从偏移量为4的地方存储。s2中c 变量与a变量中间填充了一个字节,是因为a为short类型,要在偏移量为6而不是5的地方存储,否则无法满足偏移量为该变量所占字节数的倍数的要求。s3同理。

例子:

Struct A
{
Int a;
Double b;
Float c;
};
Struct B
{
Char e[2];
Int f;
Double g;
Short h;
Struct A I;
};

cout<<sizeof(A)<<endl;//24
cout<<sizeof(B)<<endl;//48

Sizeof(A)=24; 因为 int为4,double为8,float为4,总长为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。


参考连接:

http://blog.sina.com.cn/s/blog_7595927101019dff.html