内存对齐原则
1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第
一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要
从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,
结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存
储。
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从
其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b
里有char,int ,double等元素,那b应该从8的整数倍开始存储.)。
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大
成员的整数倍.不足的要补⻬。
实例解读
1.两个结构体里放相同变量。未嵌套结构体。变量的顺序不同。根据内存对齐原则看内存对齐的结果:
// RTObj1 和 RTObj2 没有嵌套 结构体。 对齐的的时候遵守第一和第三个原则
struct RTObj1 {
double rt_d; // 8 (从0开始,占位 0-7)
char rt_c1; // 1 (char类型 1字节 1的倍数开始存储, 占位 8)
int rt_i; // 4 (int类型 4字节 4的倍数开始存储, 占位 12-15)
char rt_c2; // 1 (char类型 1字节 1的倍数开始存储 占位 16)
// 第三个原则收尾 最大为 double 类型 8 字节 所以要以8的倍数为结尾
} rtObj1; // result = 24
struct RTObj2 {
double rt_d; // 8 (从0开始,占位 0-7)
int rt_i; // 4 (int类型 4字节 4的倍数开始存储, 占位 8-11)
char rt_c1; // 1 (char类型 1字节 1的倍数开始存储 占位 12)
char rt_c2; // 1 (char类型 1字节 1的倍数开始存储 占位 13)
// 第三个原则收尾 最大为 double 类型 8 字节 所以要以8的倍数为结尾
} rtObj2; // result = 16
输出结果: rtObj1=24 : rtObj2=16
顺便打印了rtObj1里各个变量的地址:输出结果如下:
&rtObj1.rt_d 0x100002100
&rtObj1.rt_c1 0x100002108
&rtObj1.rt_i 0x10000210c
&rtObj1.rt_c2 0x100002110
与注释书写的占位情况符合
2.结构体嵌套结构体,主要为了看内存对齐的第二原则。
struct RTObj3 {
int rt_i; // 4 (从0开始,占位 0-3)
char rt_c1; // 1 (char类型 1字节 1的倍数开始存储 占位 4)
double rt_d; // 8 (double类型 8字节 8的倍数开始存储 占位 8- 15)
// 第三个原则收尾 最大为 double 类型 8 字节 所以要以8的倍数为结尾
} rtObj3; // result = 16
struct RTObj4 {
char rt_c; // 1 (从0开始,占位 0)
struct RTObj3 obj; // 16 (结构体, 16字节, 内部最大元素为 8字节, 根据内存对齐第二原则, 要以8的倍数开始存储, 占位 8 - 23)
int rt_i; // 4 (int类型 4字节 4的倍数开始存储, 占位 24-27)
// 第三个原则收尾 最大为 double 类型 8 字节 所以要以8的倍数为结尾
} rtObj4; // result = 32
输出结果:rtObj3=16 : rtObj4=32
顺便打印了rtObj4里各个变量的地址:输出结果如下:
&rtObj4.rt_c 0x100002100
&rtObj4.obj.rt_i 0x100002108
&rtObj4.obj.rt_c1 0x10000210c
&rtObj4.obj.rt_d 0x100002110
&rtObj4.rt_i 0x100002118