导引
首先看一个例子:



从图中看出,打印结果不同,这是为什么呢?
基础知识(arm64)
char 1字节; short 2字节 ; int 4字节; double 8字节
对齐原则
1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存储。
2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补⻬。
这是内存对齐原则,接下来我们要对其进行一一验证,探究出为什么打印结果不同。
验证
MyStructOne(初始 size = 0)
1. a占用1字节,起始位置为0,即offset = 0,size = 1。
2. b占用2字节,根据原则1,b的起始位置要为2的倍数,所以b起始位置为2(size + 1),即offset = 2, size = 1 + 1 + 2 = 4。
3. c占用8字节,根据原则1,c的起始位置要为8的倍数,所以c起始位置为8(size + 4),即offset = 8,size = 4 + 4 + 8 = 16。(同b)
4. d占用4字节,根据原则1,d的起始位置要为4的倍数,所以d起始位置为16(size 占用0-15位),即offset = 16,size = 16 + 4 = 20。
5. 最终size不满足原则3,那么size = 24(为8*3)。
最终得出结果: sizeof(MyStructOne) = 24
MyStructTwo(初始 size = 0)
1. c占用8字节,起始位置为0,即offset = 0,size = 8。
2. a占用1字节,根据原则1,c的起始位置要为1的倍数,所以c起始位置为8(size),即offset = 8,size = 8 + 1 = 9。
3. b占用2字节,根据原则1,b的起始位置要为2的倍数,所以b起始位置为10(size + 1),即offset = 10, size = 9 + 1 + 2 = 12。
4. d占用4字节,根据原则1,d的起始位置要为4的倍数,所以d起始位置为12(size占用0-11位),即offset = 12,size = 12 + 4 = 16。
5. size满足原则3,size = 16。
最终得出结果:sizeof(MyStructTwo) = 16
为了验证原则2,我在MyStructOne里添加MyStructThree(已算出大小为24),如下图:


从图中可以看出MyStructOne为48,MyStructThree作为MyStructOne里的元素,MyStructThree内最大的为8,所以MyStructThree的起始位置应该为8的倍数,MyStructOne前边的元素大小为24,MyStructThree起始位置为24,最终MyStructOne为48。
总结
1. 编译器在进行编译时,对每个数据的在内存的排放都是有一定规则的。
2. 数据声明顺序的不同会导致内存结构的不同。这样我们可以通过按照数据类型来调整结构体内部的数据的先后顺序来尽量减少内存的消耗。
补充
内存对齐的好处(原因)
1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
网友评论