一、知识补充-内存对齐算法
8字节对齐
| 字节数(字节) | 所开辟字节大小(字节) |
|---|---|
| 0~8 | 8 |
| 9~16 | 16 |
| 17~24 | 24 |
| ... | 8*n |
8字节对齐算法公式: (x + 7)& ~7
例如:( 12 + 7 )& ~7 = 16
另外一种算法: x >> 3 << 3
同理16字节对齐算法 : (x+15) &~15
从objc源码中,我们可以得知,在iOS中时才用16字节对齐
inline size_t instanceSize(size_t extraBytes) const {
if (fastpath(cache.hasFastInstanceSize(extraBytes))) {
return cache.fastInstanceSize(extraBytes);
}
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
// Class's ivar size rounded up to a pointer-size boundary.
uint32_t alignedInstanceSize() const {
return word_align(unalignedInstanceSize());
}
static inline size_t word_align(size_t x) {
return (x + WORD_MASK) & ~WORD_MASK;
}
# define WORD_MASK 7UL
二、结构体内存对齐
比较两个结构体的内存大小
struct LGStruct1 {
char b; // 1
int c; // 2 3 [ 4 5 6 7 ]
double a; // 8 9 10 11 12 13 14 15
short d; // 16 17 24
}struct1;
struct LGStruct2 {
double a; //
int b;
char c;
short d;
}struct2;
根据内存对齐原则
struct LGStruct1 {
char b; // 1
int c; // 2 3 [ 4 5 6 7 ]
double a; // 8 9 10 11 12 13 14 15
short d; // 16 17 24
}struct1;
struct LGStruct2 {
double a; // 0 1 2 3 4 5 6 7
int b; // 8
char c; // 9 10 11 [ 12 ]
short d; // 13 [ 14 15 ] 16
}struct2;
所以得到LGStruct1的内存大小为 24,LGStruct2的内存大小为16
再来看一个:
struct LGStruct3 {
double a; // 0 - 7 8字节*1
int b; // 8 - 11
char c; // 12。 8字节*2
struct LGStruct1 str1; // 24字节*1
short d; // 40 - 41
int e; // 44 -47 8字节*3
struct LGStruct2 str2; // 16字节*1
}struct3;
所以LGStruct3 是64字节
验证
NSLog(@"%lu-%lu-%lu",**sizeof**(struct1),**sizeof**(struct2),**sizeof**(struct3));
// 24-16-64
内存对齐原则
1:数据成员对⻬规则:结构(struct)(或联合(union))的数据成员,第 ⼀个数据成员放在offset为0的地⽅,以后每个数据成员存储的起始位置要 从该成员⼤⼩或者成员的⼦成员⼤⼩(只要该成员有⼦成员,⽐如说是数组, 结构体等)的整数倍开始(⽐如int为4字节,则要从4的整数倍地址开始存 储。 min(当前开始的位置m n) m = 9 n = 4 9 10 11 12
2:结构体作为成员:如果⼀个结构⾥有某些结构体成员,则结构体成员要从 其内部最⼤元素⼤⼩的整数倍地址开始存储.(struct a⾥存有struct b,b ⾥有char,int ,double等元素,那b应该从8的整数倍开始存储.)
3:收尾⼯作:结构体的总⼤⼩,也就是sizeof的结果,.必须是其内部最⼤ 成员的整数倍.不⾜的要补⻬。