1.分别对齐规则【每个成员分别按自己的方式对齐】
成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐.
2.首地址整数倍规则【结构体对象在内存中的地址为其基值的整数倍】
3.成员偏移规则
结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding)【每个成员相对于首地址的偏移量是以该成员大小为基值的整数倍】【从第一个成员依次往后排,获取合适的空闲地址,中间被编译器填充】
4.结构体长度成倍规则
结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节(trailing padding)
C++11运算符alignof(type)可以获取当前实现下对应类型的字节对齐方式=>获取当前类型的字节对齐的地址倍数的基值【该型变量在内存中的地址必定为该地址的整数倍】若代入的是结构体类型除了地址为其基值的整数倍外,结构体的长度也为该基值的整数倍
//成员对齐大小,复合类型的对齐大小是其成员对齐大小中的最大值;基本类型的对齐大小就是其本身的大小
struct Test2
{
int t;
union
{
struct
{
//此时sizeof(Test2)大小是24;匿名结构体是按8字节对齐的,整体注入到union大小就是16(8+4,调整到8的边界);匿名union的大小也是16,然后加上t的大小4;这时就是20;
//而Test2的对齐大小是其成员的对齐大小的最大的那个,如果遇到复合类型成员,复合类型成员的对齐大小,也是复合类型的成员的对齐大小的最大的那个【递归规则】;
// 最后递归到匿名结构体double基本类型成员的对齐大小【基本类型成员的对齐大小就是其本身的大小】
double a;
int b;
};
int c;
};
};
更新说明:
1.分别对齐规则:成员对齐有一个重要的条件,即每个成员分别对齐.即每个成员按自己的方式对齐.
2.首地址整数倍规则【结构体对象在内存中的地址为其对齐大小的整数倍】
3.成员偏移规则
结构体每个成员相对于结构体首地址的偏移量(offset)都是成员的对齐大小的整数倍;
4.占用对齐规则:每个成员占用结构体空间的大小,是这个成员的对齐大小的整数倍【根据成员的理论大小向上取整(以成员的对齐大小)】(这里说的成员的理论大小是:若是基本类型成员就是其sizeof的大小,若是复合类型成员,则是其复合类型的直接子成员分别sizeof大小之和【只算直接的这个复合类型成员的下一层直接成员的实际大小(对齐后的大小,sizeof就是实际对齐后的大小)】)
即算成员的实际大小(对齐后的大小),是根据其成员的理论大小向上取整到成员的对齐大小的整数倍;【这个整数倍取到可以容纳理论大小的最低整数倍为止】;
成员的理论大小:若是基本类型成员就是其sizeof大小;若不是则分别计算该成员的各个直接子成员的实际大小(对齐后)之和(注这里是直接子成员,而且是直接子成员的实际对齐后的大小);【此时又在此处应有递归规则,成员的每个成员的实际大小的计算又递归下一层成员进行计算】
成员的对齐大小是根据递归规则确定(见下)
类型的对齐大小:
基本类型的对齐大小,就是其类型的大小(sizeof得到的大小)
复合类型的对齐大小,是其成员的对齐大小的最大的那个;若复合类型内还有复合类型成员,则递归应用此规则;
这里有三个概念
成员的对齐大小=>见上概念比较清楚
成员的理论大小=>是该成员的直接子成员的实际大小之和
成员的实际大小=>是该成员的理论大小向上取整到该成员对齐大小的整数倍
基本类型成员的=>对齐大小,理论大小,实际大小三个是一样的;上述规则是不断相互递归作用,直到遇到基本类型成员中止