引言
什么是结构体?iOS 开发入门的时候都会使用frame对控件的大小位置进行设置,这里的frame 就是 CGRect的结构体实例。细看一下结构体里面是
CGRect 里面是 GCPoint 和 CGSize,GCPoint 和 CGSize里面是 CGFloat基础数据类型,到底了哈!接下来我们玩一下,看看结构体所占内存大小。
一、结构体的大小
在探索结构体的大小之前我们先统计一下基础类型的大小:
| c | oc | 32位 | 64位 |
|---|---|---|---|
| bool | BOOL(64位) | 1 | 1 |
| signed char | (_ _signed char)int8_t、BOOL(32) | 1 | 1 |
| unsigned char | Boolean | 1 | 1 |
| short | int16_t | 2 | 2 |
| unsigned short | unichar | 2 | 2 |
| int int32_t | NSInter(32位)、Boolean_t(32位) | 4 | 4 |
| unsigned int | NSUInter(32位)、boolean_t642位) | 4 | 4 |
| long | NSInter(64位) | 4 | 8 |
| unsigned long | NSUInter(64位) | 4 | 8 |
| long long | int64_t | 8 | 8 |
| float | CGFloat(32位) | 4 | 4 |
| double | CGFloat(64位) | 8 | 8 |
我们首先创建2个结构体 LGTeacher 和 LGStudent 如图所示:
然后我们打印
tecaher 和 student 的大小
打印结果:
我的天呐!我们的
LGTeacher 和 LGStudent 大小居然不一样这是什么情况呢?
这个就涉及到了内存对齐原则,接下来我们详细探索内内原则。
二、内存对齐原则
内存对齐原则有3条
- 结构(struct)(或联合(union))的数据成员,第⼀个数据成员放在offset为0的地⽅,以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩(只要该成员有⼦成员,⽐如说是数组,结构体等)的整数倍开始(⽐如int为4字节,则要从4的整数倍地址开始存储.
- 结构体作为成员:如果⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤元素⼤⼩的整数倍地址开始存储.(struct a⾥存有struct b,b⾥有char,int ,double等元素,那b应该从8的整数倍开始存储.)
- 收尾⼯作:结构体的总⼤⼩,也就是sizeof的结果,必须是其内部最⼤成员的整数倍.不⾜的要补⻬。
1、验证对齐原则1
根据上面的三大原则1我们来手动计算一下 LGTeacher 和 LGStudent 的大小,来验证一下原则是否正确,我们先把 LGTeacher 和 LGStudent 中的成员变量的大小标记出来如图:
接下来我们根据规则计算大小,结果如图:
这个计算结果和我们上面的打印结果是一致的,所以我们验证了内存对齐的三大原则
1。
2、验证对齐原则2
我们验证三大原则用的是基础数据类型作为成员变量,那么如果换了其他的呢?说干就干,我们创建一个 LGDriver 结构体,并将 LGTeacher 作为他的成员变量,如图所示:
(为了省事其他成员变量直接复制
LGStudent)我们将LGTeacher 和 LGStudent 的成员变量展开,计算一下:
打印验证我们的计算:
结果:
是不是巧合呢?我们再加一个结构体成员变量
LGStudent 并计算如图:
计算结果为
56 不变动答应代码我们再打印一下:
哦豁!一样的成功验证了对齐原则二条(从成员结构体内部最⼤元素⼤⼩的整数倍地址开始存储)
3、验证对齐原则3
在1和2的验证中已经间接验证了3,不刻意再去验证了。