结构体的内存对齐

239 阅读3分钟

引言

什么是结构体?iOS 开发入门的时候都会使用frame对控件的大小位置进行设置,这里的frame 就是 CGRect的结构体实例。细看一下结构体里面是

rect.jpg CGRect 里面是 GCPointCGSizeGCPointCGSize里面是 CGFloat基础数据类型,到底了哈!接下来我们玩一下,看看结构体所占内存大小。

一、结构体的大小

在探索结构体的大小之前我们先统计一下基础类型的大小:

coc32位64位
boolBOOL(64位)11
signed char(_ _signed char)int8_t、BOOL(32)11
unsigned charBoolean11
shortint16_t22
unsigned shortunichar22
int int32_tNSInter(32位)、Boolean_t(32位)44
unsigned intNSUInter(32位)、boolean_t642位)44
longNSInter(64位)48
unsigned longNSUInter(64位)48
long longint64_t88
floatCGFloat(32位)44
doubleCGFloat(64位)88

我们首先创建2个结构体 LGTeacherLGStudent 如图所示: 截屏2021-06-08 下午9.51.00.png 然后我们打印 tecaherstudent 的大小 截屏2021-06-08 下午9.32.56.png 打印结果: 截屏2021-06-08 下午9.51.30.png 我的天呐!我们的 LGTeacherLGStudent 大小居然不一样这是什么情况呢? 这个就涉及到了内存对齐原则,接下来我们详细探索内内原则。

二、内存对齐原则

内存对齐原则有3条

  1. 结构(struct)(或联合(union))的数据成员,第⼀个数据成员放在offset为0的地⽅,以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩(只要该成员有⼦成员,⽐如说是数组,结构体等)的整数倍开始(⽐如int为4字节,则要从4的整数倍地址开始存储.
  2. 结构体作为成员:如果⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤元素⼤⼩的整数倍地址开始存储.(struct a⾥存有struct b,b⾥有char,int ,double等元素,那b应该从8的整数倍开始存储.)
  3. 收尾⼯作:结构体的总⼤⼩,也就是sizeof的结果,必须是其内部最⼤成员的整数倍.不⾜的要补⻬。

1、验证对齐原则1

根据上面的三大原则1我们来手动计算一下 LGTeacherLGStudent 的大小,来验证一下原则是否正确,我们先把 LGTeacherLGStudent 中的成员变量的大小标记出来如图:

截屏2021-06-08 下午10.18.33.png

接下来我们根据规则计算大小,结果如图: 截屏2021-06-08 下午11.05.06.png 这个计算结果和我们上面的打印结果是一致的,所以我们验证了内存对齐的三大原则1

2、验证对齐原则2

我们验证三大原则用的是基础数据类型作为成员变量,那么如果换了其他的呢?说干就干,我们创建一个 LGDriver 结构体,并将 LGTeacher 作为他的成员变量,如图所示:

截屏2021-06-08 下午11.15.25.png (为了省事其他成员变量直接复制 LGStudent)我们将LGTeacherLGStudent 的成员变量展开,计算一下: 截屏2021-06-09 上午10.14.18.png 打印验证我们的计算: 截屏2021-06-08 下午10.55.05.png 结果: 截屏2021-06-08 下午11.20.59.png 是不是巧合呢?我们再加一个结构体成员变量 LGStudent 并计算如图:

截屏2021-06-09 上午10.16.15.png 计算结果为 56 不变动答应代码我们再打印一下: 截屏2021-06-09 上午10.17.50.png 哦豁!一样的成功验证了对齐原则二条(从成员结构体内部最⼤元素⼤⼩的整数倍地址开始存储)

3、验证对齐原则3

12的验证中已经间接验证了3,不刻意再去验证了。