在讨论结构体内存对齐原理之前,首要介绍下iOS中获取内存巨细的三种方法

获取内存巨细的三种方法

获取内存巨细的三种方法别离是: sizeof,class_getInstanceSize,malloc_size

sizeof

  • siz嵌套分类汇总的操作步骤eof是一个操作符,不是函数
  • 咱们一般用 sizeof 核算内存巨细时,传入的首要政策是数据类型,这个在编译器的编译阶段苹果手机(即编译时)就会供认巨细而不是在运行时供认。
  • sizeof 终究得到的作用是该数据类型占用空间的巨细

class_getInsios15tanc嵌套是什么意思eSize

这个方法是runtime供给的api,用于获取类的实例政策所占用的内存巨细,并返回具体的字节数,其本质就是获取实例政策中成员变量的内存巨细

malloc_size

这个函数是获取体系实践分配的内存算法的有穷性是指巨细

能够经过下面代码的输出作用来验证咱们上面的说法

#import &l嵌套查询sql句子t;Foundation/Foundation.h>
#import "WJPerson.h"
#import <objc/run算法是什么time.h>
#import <malloc/malloc.源码本钱h>
int main(int argc, const cha源码之家r * argv[]) {
@autoreleasepool {
WJPerson *person = [[WJPerso算法规划与剖析n alloc] init];
NSLog(@"person政策类型占用的内存巨细:%lu",s苹果摊上新诉讼izeof(person));
NSLog(@"person政策实践占用的内存巨细:%lu"ios下载,class_getInstanceSize([person ciOSlass]苹果摊上新诉讼));
NSLog(@算法的时刻复杂度是指什么"person政策实践分配的内存巨细:%lu",malloc_size((__bridge const void*)算法的时刻复杂度是指什么(person)));
}
return 0;
}

以下是打印作用

探究结构体内存对齐

总结

  • sizeof:核算类型占用的内存巨细,其间能够放 根柢数据类型、政策、指针

    • 关于int这样的根柢数据而言,sizeof 获取的就是数据类型占用的内存巨细,不同的数据类型所占用的内存巨细是不相同的

    • 关于WJPerioslauncher14安卓版son 界说的实例政策而言,其政策类型的本质就是一个结构体(即 struct objc_object)的指针源码,所以源码网站sizeof(person)打印的是政策person指针巨细,咱们知道一个指针的内存巨细是8,所以si算法的五个特性zeof(per苹果官网son) 打印是 8。留意:这儿的8字节isa指针一点联络都没有!!!)

    • 关于指针而言,sizeof打印的就是8,因为一个指针内存巨细是8

  • class_getInstanceSize:核算政策实践占用的内存巨细,这个需求依据类的特征而改嵌套查询变,假如自界说类没有自界说特源码编辑器手机版下载色,仅仅仅仅承继自NSObject,则类的实例政策实践占用源码编辑器编程猫下载的内存巨细是8算法工程师,能够简嵌套查询sql句子略理解为8字节对齐

  • malloc_size:核算政策实践分配的内存巨细,这个是由体系完结的,嵌套能够从上面的打印作用看出,实践分配的和实践占用的内存巨细并不持平

结构体内存对齐

接下来,咱们首要界说两个结构体,苹果别离核算ios是什么意思他们的内存巨细,以此来引进今日的正题:结构体内存对齐原理


struct WJStruct1 {
double a;
char b;嵌套是什么意思
int c;
short d;
}struct1;
struct WJStruct2 {ios是什么意思
double a;
int b;
char c;
short d;
}struct2;
//核算 结构体占用的内存巨细
NSLog(@"%lu算法是什么-%lu",sizeof(struct1),sizeof(struct2));

打印作用如下:
探究结构体内存对齐

从打印源码编辑器手机版下载作用咱们能够看出一个问ioslauncher题,两个结构体乍一看,没什么差嵌套结构异,其间界说的变量变量类型都是一致的,仅有的差异仅仅在于界说变量的次序不一致,那为什么他们占用的内存巨细不持平呢?其实这就是iOS中的内存字节对齐现象

内存对齐准则

能够将内存对齐准则能够理解为以下ios14.4.1更新了什么几点:

  • 源码年代准则一】源码共享网 数据成员的对齐规矩能够理解为min(m, n) 的公式, 其间 m标明当时成员的开始方位, n标明当时成员所需求的位数。假如满意条件 m 整除 n (即 m % n苹果官网 == 0), nm 方位开始存源码网站储, 反之继续检查 m+1 能否整除 n, 直到能够整除, 从而就供认了当时成员的开始方位
  • 【准则二】数据成员为结构体:当结构体嵌套了结构体时,作为数据成员的结构体的本身长度作为外部结构体的嵌套是什么意思最大成员的内存巨细,比方结构体a嵌套结构体bb中有char、int、double等,则b的本身长度源码8
  • 【准则三】最后结构体的内存巨细有必要是结构体中最大成员内存巨细整数倍,缺嵌套函数少的需求补齐。

验证对齐规矩

下表是各种数据类型iOS中的占用内存巨细,依据对应类型来核算结构体中内存巨细

探究结构体内存对齐

咱们能够经过下图来阐明下为什么两个结构体 WJStruct1 & WJStruct2的内存巨细打印不一致的情况,如图所示

探究结构体内存对齐

  • 依据内存对算法的五个特性齐规矩得出WJStruct1苹果官网内存巨细是18 ,但源码编辑器18源码编辑器手机版下载不是最大变量的字节数8的整数倍,18向上取整到24,首要是因为248的整数倍,所以 si苹果13zeof(struct1) 的作用是 24
  • 依据内存对齐规矩得出WJStruct2的内存巨细是16 ,16刚好是8的整数倍,所以源码网站sizeof(struct2) 的作用是 16算法剖析的目的是

结构体嵌套ios最好玩的手游结构体

上面的两个结构体仅仅简略的界说数据成员,下面来一个比较复杂的,结构体中嵌套结构体的内存巨细核算情况

首要界说一苹果8个结构体WJStruct3,在WJStruct3中嵌套WJStruct1,如下所示

struct WJSt源码编辑器r算法的有穷性是指uct3 {
double a;              //8
int b;                 //4
char c;                //1
sh嵌套循环ort d;               //2
int e;                 //4
struct WJStruct1 str;  //24
}struct3;
//打印 WJStruct3 的内存巨细
NSLog(@苹果11"struct3内存巨细:%lu", sizeof(struct3));
NSLog(@算法的有穷性是指"struct3中结构体成员内存巨细:苹果11%lu", sizeof(struct3源码本钱.striOS));

打印作用如下:
探究结构体内存对齐

依据ios14.4.1更新了什么内存对齐规矩,咱们能够画WJStruct3的内存分布图:

探究结构体内存对齐

剖析WJStruct3的内存核算:

  • 变量adouble类型8个字节,从0开始,此刻min(0,8),即 0-7 存储 a
  • 变量bint类型4个字节,从8开始,此刻min(8,4)8能够整除4,即 8-1源码本钱1 存储 b
  • 变量cchar类型1个字节,从12开始,此刻min(12, 1)12能够整除1,即12 存储 c
  • 变量dshort类型2个字节,从1ioslauncher3开始,此刻min(13,2),不能整除,+1后能够整除,即 14-15源码买卖网站源码 存储 d
  • 变量eint类型4个字节,从16开始,此刻min(16,4)16能够整除416-19 存储 e
  • 结构体成员strstr 是一个结构体,依据内存对齐准则二,结构体成员要从其内部最大成员巨细的整数倍开始存储,而WJSt苹果摊上新诉讼ruct2ios下载最大的源码之家成员巨细为8,所源码买卖网站源码str要从8的整数倍开始,当时是从20开始,所以不契合要求,需求往后移动到24248的整数倍,契合内存对齐准则,所以 24-47 存储 str

因此WJStruct3的需求的内存巨细为 48 字节,而 WJStruct3 中最大变量为str, 其最大成员内存字节数为8,依据内存对齐准则,所以 WJStruct3 实践的内存巨细有必要是 8 的整数倍,48正好是8的整数倍,所以 sizeof(WJStruct3) 的作用是 48

内存优化(特征重排)

WJStruct1 经过内存字节对齐准则,添加了8个字节源码编辑器手机版下载,而 WJStruct2 经过内存字节对齐准则,经过4+1+2的组合,只需求补齐一个字节即可满意字节对齐规矩,这儿得出一个结论结构体内存巨细与结构体成员内存大ios模拟器小的次序有关

假如是结构体中数据成员是依据内存从小到大的次序界说的,依据内存对齐规矩来核算结构源码编辑器编程猫下载体内存巨细,需求添加有较大源码年代的内存padding即内存占位符,苹果11才华满意内存对齐规矩,比较糟蹋内存

假如是结构体中数据成员是依据内存从大到小的次序界说的,依据内存对齐规矩来核算结构体内存巨细,咱们只需求补齐少数内苹果电影存padding即可满意堆存对齐规矩,这种方法就是苹果中选用的,使用空间换时刻,算法的有穷性是指将类中的特征进行重排,来抵达优化内存的目的

以下面这个例子来进行阐明 苹果中特征重排,即内存优化

  • 界说一个自界说 WJPerson苹果手机 类,并界说几个特征
@interface WJPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long hios14.4.1更新了什么eight;
@嵌套proios15perty (嵌套结构nonatomic) char c1;
@property (nonatomic) char c2;
@end
  • main 中创立 WJPerson 的实例政策,并对其间的几个特征赋值
int main(int argc, const char * argv[]) {
@autoreleasepool {
WJPerson *person = [WJPerson all苹果手机oc];
person.name      = @"Jem";
person.nick苹果电影Name  = @"WJ";
person.age       = 18;
person.c1        = 'a';
person.c2        = 'b';
NS源码之家Log(@"%@"ios是什么意思,person);
}
return 0;
}
  • 断点调试person,依据WJP算法是什么erson的政策地址,查找出特征的值

探究结构体内存对齐

当咱们向经过0x0000001200006261地址找出age嵌套是什么意思等数据时,发苹果13现读源码编辑器编程猫不到,这儿无法找出值的原因是苹果中针对age、c1源码买卖网站源码、c2特征的内存进行源码本钱了重排,因为age类型占4个字节ios最好玩的手游c源码本钱1c2类型char别离占1个字节,经过4+1+1的方法,按照8字节对齐,缺少补齐的方法存储在同一块内存中,

  • age 的读取经过 po 0x00000012(18)
  • c1 的读取经过 x/c 0x61(a)
  • c2 的读取经过 x/c 0x62(b)

总结

所以,这儿能够总结下苹果源码共享网中的内存对齐思维:

  • 大部分的内存都是经过固定的内存块进行读取,

  • 虽然咱们在内存中选用了内存对齐的方法,但并不是一切的内存都能够进行糟蹋的,苹果会自动对特征进行重排,以此来优化内存

  • 字节对齐终究选用多少字节对齐?咱们能够经过obj源码编辑器编程猫下载c4的源码来进行剖析

    • class_getInstanceSize:是选用苹果手机8字节对齐,参照的政策的特征内存巨细
    • malloc_size:选用16字节对齐,参照的整个政策的内存巨细,政策实践分配的内存源码年代巨细有必要是1ioslauncher14安卓版6的整数倍
  • 内存对齐算法原理:k + 15 >> 4 << 4 ,其间 右移4 + 左移4相当于将后4位抹零,跟 k/16 * 16相同 ,是16字节对齐算法,小于16就成0了.