内存对齐的三条规则
规则1:结构体的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员放在offset为该数据成员大小的整数倍的地方。如:int在32位机为4字节,则要从4的整数倍地址开始存储。
规则2:如果一个结构体B里嵌套另一个结构体A,则结构体A应从offset为A内部最大成员的整数倍的地方开始存储。(struct B里存有struct A,A里有char、int、double等成员,那A应该从8的整数倍开始存储。)结构体A中的成员的对齐规则仍满足原则1、原则2。
Tips:
- 结构体A所占的大小为该结构体成员内部最大元素的整数倍,不足补齐。
- 不是直接将结构体A的成员直接移到结构体B中
规则3:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足要补齐。
在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是
struct A{ int a; short b; int c; char d; }; struct B{ int a; short b; char d; int c; };
A:a占4个字节,b占2个字节,但因为c占4个字节,为了满足(结构体每个成员相对于结构体首地址的偏移量offset都是成员大小的整数倍),b需要占4个字节,为了满足(结构体总大小是内部最大成员整数倍),d需要4个字节。所以一共16个字节。
类型 int short int char 地址 0~3 4~7 8~11 12 累计所占内存(字节) 4 8 12 13 按照规则(最大成员整数倍) 16 B:a占4个字节,b占2个字节,d占1个字节,但c占4个字节
a:0~3
b:4~5
d:6 6是1的整数倍 为满足(结构体每个成员相当于结构体首地址的偏移量都是成员大小的整数倍)所以d需要两个字节,这样c的首地址偏移量就是4的整数倍
c:8~12
类型 int short char int 地址 0~3 4~5? 6 8~12 累计所占内存(字节) 4 6 8 12 按照规则(最大成员长度整数倍) 12
总结:
1、各个成员首地址必须是自身大小的整数倍
对齐长度/结构体长度如果不是整数则需要补齐
eg:double 令当前结构体长度为a
首地址为:(8-(a%8))+a
2、结构体总大小(sizeof结果)必须是最大成员大小整数倍
若有指定字节:??
1、各成员首地址是min[n,自身大小]整数倍
2、结构体总大小是min[n,最大成员大小]整数倍