区块链技术博客
www.b2bchain.cn

iOS 底层之内存对齐求职学习资料

本文介绍了iOS 底层之内存对齐求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

前言

内存对齐这个词总是环绕在我们耳边,但是真正的含义我们却一知半解,总感觉被迷雾笼罩,今天就探索下内存对齐,把它神秘的面纱揭开。俗话说实践是检验真理的唯一标准,直接上案例。下面打印对象类型的内存大小,对象实际的内存大小和系统分配的内存大小。代码和打印如下:

LWPerson * person =  [LWPerson alloc]; person.name = @"person"; person.age = 18; LWPerson * newPerson;  NSLog(@"对象类型的内存大小--%lu",sizeof(person)); NSLog(@"对象实际的内存大小--%lu",class_getInstanceSize([person class])); NSLog(@"系统分配的内存大小--%lu",malloc_size((__bridge const void *)(person))); NSLog(@"=================="); NSLog(@"对象类型的内存大小--%lu",sizeof(newPerson)); NSLog(@"对象实际的内存大小--%lu",class_getInstanceSize([newPerson  class])); NSLog(@"系统分配的内存大小--%lu",malloc_size((__bridge const void *)(newPerson)));  2021-06-08 11:16:28.097465+0800 alignStyle[73542:9731629] 对象类型的内存大小--8 2021-06-08 11:16:28.097520+0800 alignStyle[73542:9731629] 对象实际的内存大小--24 2021-06-08 11:16:28.097562+0800 alignStyle[73542:9731629] 系统分配的内存大小--32 2021-06-08 11:16:28.097583+0800 alignStyle[73542:9731629] ================== 2021-06-08 11:16:28.097607+0800 alignStyle[73542:9731629] 对象类型的内存大小--8 2021-06-08 11:16:28.097629+0800 alignStyle[73542:9731629] 对象实际的内存大小--0 2021-06-08 11:16:28.097649+0800 alignStyle[73542:9731629] 系统分配的内存大小--0

结果分析:

  • sizeof:对象类型的内存大小,sizeof 是一个操作符号,不是函数。计算的是传进来的数据类型的大小,这个在编译时期就已经确定。所以 sizeof(person)sizeof(newPerson) 都是8字节,因为它们的本质是结构体指针。

  • class_getInstanceSize:对象实际的内存大小,内存大小是由类的成员变量的大小决定。实际上并不是严格意义上的对象的内存的大小,因为内存进行了8字节对齐,核心算法是define WORD_MASK 7UL ((x + WORD_MASK) & ~WORD_MASK。 所以 person 的内存大小是 24 而不是 20newPerson 只是声明了一个变量,并没有开辟内存,所以大小是0

  • malloc_size 系统分配的内存大小是按16字节对齐的方式,即分配的大小是16的倍数 ,不足16的倍数系统会自动填充字节,注意系统的16字节对齐是在实际的内存大小(经过8字节对齐)的基础上。

问题:
class_getInstanceSizemalloc_size 底层做了什么? 你怎么知道
class_getInstanceSize8字节对齐的呢? 而malloc_size16字节对齐的呢?
class_getInstanceSizemalloc_size探索流程会放在文章的结尾。

内存对齐

前言我们发现对象实际的内存大小是8字节对齐,那么到底是怎么对齐的。引出我们的重点内存对齐。

各类型所占字节

在这里整理些基本数据类型在不同系统下的字节大小,方便大家查看。

iOS 底层之内存对齐

需要内存对齐的原因

  • 内存是以字节为基本单位,cpu在存取数据时,是以块为单位存取,并不是以字节为单位存取。频繁存取未对齐的数据,会极大降低cpu的性能。字节对齐后,会减低cpu的存取次数,这种以空间换时间的做法目的降低cpu的开销。

  • cpu存取是以块为单位,存取未对齐的数据可能开始在上一个内存块,结束在另一个内存块。这样中间可能要经过复杂运算在合并在一起,降低了效率。字节对齐后,提高了cpu的访问速率。

内存对齐原则

  • 1: 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在 32 位为4字节,则要从4的整数倍地址开始存储。

  • 2: 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

  • 3: 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍.不足的要补齐。

内存对齐原则描述的那么复杂,搞我心态是吧,必须实例解我疑惑

结构体内存对齐(无嵌套)

对象的本质就是结构体,对象的底层实现是结构体。内存对齐实际上可以看做是结构体内存对齐,只不过系统对实例化的对象进行了内存优化。接下来实例探究下结构体内存对齐

struct LWStruct1{     double  a; // 8     int     b; // 4     short   c; // 2     char    d; // 1 }LWStruct1;  struct LWStruct2{     double  a; // 8     char    d; // 1     int     b; // 4     short   c; // 2 }LWStruct2;  int main(int argc, char * argv[]) {     @autoreleasepool {         NSLog(@"-----%lu-----%lu",sizeof(LWStruct1),sizeof(LWStruct2));     }     return 0; }  2021-06-08 15:02:54.392903+0800 alignStyle[74021:9798038] -----16-----24

结果分析发现 LWStruct1LWStruct2 所包含的变量是一样的,只是位置不一样,但是内存大小不一样,为什么? 这就是结构体内存对齐。

下面就根据内存对齐原则进行简单的计算和分析

LWStruct1内存大小详细过程(min(m,n) m表示当前开始的位置,n表示大小)

  • 变量a: 占8个字节,offert从0开始, min(0,8), 即0 ~ 7 存放a
  • 变量b: 占4个字节,offert从8开始, min(8,4), 即8 ~ 11 存放b
  • 变量c: 占2个字节,offert从12开始,min(12,2),即12 ~ 13存放c
  • 变量d: 占1个字节,offert从14开始,min(14,1),即14存放d

结果显示 LWStruct1 的实际的内存大小是15字节LWStruct1中最大的变量是a占个8 字节。所以LWStruct1的实际内存大小必须是8的整数倍,15不是8的整数倍,向上取整,不足的自动补齐为16字节。最后LWStruct1的内存大小为16字节
LWStruct1解析图如下

iOS 底层之内存对齐

LWStruct2内存大小详细过程

  • 变量a: 占8个字节,offert从0开始,min(0,8), 即0 ~ 7 存放a
  • 变量d: 占1个字节,offert从8开始, min(8,1), 即8 存放d
  • 变量b: 占4个字节,offert从9开始, min(9,4)9 % 4 != 0,继续往后移动直到找到可以整除4的位置 1212 ~ 15 存放b
  • 变量c: 占2个字节,offert从16开始,min(16,2),即16 ~ 17 存放c

结果显示 LWStruct2 的实际的内存大小是18字节LWStruct2中最大的变量是a占个 8 字节。所以LWStruct2的实际内存大小必须是8的整数倍18不是8的整数倍,向上取整,不足的自动补齐为24字节。最后LWStruct2的内存大小为24字节

LWStruct2解析图如下

iOS 底层之内存对齐

结构体中嵌套结构体

 struct LWStruct1{     double  a; // 8     int     b; // 4     short   c; // 2     char    d; // 1 }LWStruct1;   struct LWStruct2{     double  a; // 8     char    d; // 1     int     b; // 4     short   c; // 2  }LWStruct2;  struct LWStruct3{     long    a; // 8     int     b; // 4     short   c; // 2     char    d; // 1     struct LWStruct2 lwStr; }LWStruct3;  int main(int argc, char * argv[]) {     @autoreleasepool {       NSLog(@"-----%lu-----%lu----%lu",sizeof(LWStruct1),sizeof(LWStruct2),sizeof(LWStruct3));     }     return 0; }   2021-06-08 16:28:40.819854+0800 alignStyle[74082:9819949] -----16-----24----40

LWStruct3内存大小详细过程

  • 变量a: 占8个字节,offert从0开始, min(0,8), 即0 ~ 7 存放a
  • 变量b: 占4个字节,offert从8开始, min(8,4), 即8 ~ 11 存放b
  • 变量c: 占2个字节,offert从12开始,min(12,2),即12 ~ 13 存放c
  • 变量d: 占1个字节,offert从14开始,min(14,1),即14 存放d
  • 变量lwStr:lwStr是结构体变量,内存对齐原则结构体成员要从其内部最大元素大小的整数倍地址开始存储。LWStruct2 中的最大的变量占8字节,所以offert从16开始,LWStruct2的内存大小是18字节min(16,18),即18 ~ 33存放 lwStr

结果显示 LWStruct3 的实际的内存大小是34字节LWStruct3中最大的变量是lwStra都是 8 字节。所以LWStruct3的实际内存大小必须是8的整数倍34不是8的整数倍,向上取整,不足的自动补齐为40字节。最后LWStruct3的内存大小为40字节

LWStruct3解析图如下

前言

内存对齐这个词总是环绕在我们耳边,但是真正的含义我们却一知半解,总感觉被迷雾笼罩,今天就探索下内存对齐,把它神秘的面纱揭开。俗话说实践是检验真理的唯一标准,直接上案例。下面打印对象类型的内存大小,对象实际的内存大小和系统分配的内存大小。代码和打印如下:

LWPerson * person =  [LWPerson alloc]; person.name = @"person"; person.age = 18; LWPerson * newPerson;  NSLog(@"对象类型的内存大小--%lu",sizeof(person)); NSLog(@"对象实际的内存大小--%lu",class_getInstanceSize([person class])); NSLog(@"系统分配的内存大小--%lu",malloc_size((__bridge const void *)(person))); NSLog(@"=================="); NSLog(@"对象类型的内存大小--%lu",sizeof(newPerson)); NSLog(@"对象实际的内存大小--%lu",class_getInstanceSize([newPerson  class])); NSLog(@"系统分配的内存大小--%lu",malloc_size((__bridge const void *)(newPerson)));  2021-06-08 11:16:28.097465+0800 alignStyle[73542:9731629] 对象类型的内存大小--8 2021-06-08 11:16:28.097520+0800 alignStyle[73542:9731629] 对象实际的内存大小--24 2021-06-08 11:16:28.097562+0800 alignStyle[73542:9731629] 系统分配的内存大小--32 2021-06-08 11:16:28.097583+0800 alignStyle[73542:9731629] ================== 2021-06-08 11:16:28.097607+0800 alignStyle[73542:9731629] 对象类型的内存大小--8 2021-06-08 11:16:28.097629+0800 alignStyle[73542:9731629] 对象实际的内存大小--0 2021-06-08 11:16:28.097649+0800 alignStyle[73542:9731629] 系统分配的内存大小--0

结果分析:

  • sizeof:对象类型的内存大小,sizeof 是一个操作符号,不是函数。计算的是传进来的数据类型的大小,这个在编译时期就已经确定。所以 sizeof(person)sizeof(newPerson) 都是8字节,因为它们的本质是结构体指针。

  • class_getInstanceSize:对象实际的内存大小,内存大小是由类的成员变量的大小决定。实际上并不是严格意义上的对象的内存的大小,因为内存进行了8字节对齐,核心算法是define WORD_MASK 7UL ((x + WORD_MASK) & ~WORD_MASK。 所以 person 的内存大小是 24 而不是 20newPerson 只是声明了一个变量,并没有开辟内存,所以大小是0

  • malloc_size 系统分配的内存大小是按16字节对齐的方式,即分配的大小是16的倍数 ,不足16的倍数系统会自动填充字节,注意系统的16字节对齐是在实际的内存大小(经过8字节对齐)的基础上。

问题:
class_getInstanceSizemalloc_size 底层做了什么? 你怎么知道
class_getInstanceSize8字节对齐的呢? 而malloc_size16字节对齐的呢?
class_getInstanceSizemalloc_size探索流程会放在文章的结尾。

内存对齐

前言我们发现对象实际的内存大小是8字节对齐,那么到底是怎么对齐的。引出我们的重点内存对齐。

各类型所占字节

在这里整理些基本数据类型在不同系统下的字节大小,方便大家查看。

iOS 底层之内存对齐

需要内存对齐的原因

  • 内存是以字节为基本单位,cpu在存取数据时,是以块为单位存取,并不是以字节为单位存取。频繁存取未对齐的数据,会极大降低cpu的性能。字节对齐后,会减低cpu的存取次数,这种以空间换时间的做法目的降低cpu的开销。

  • cpu存取是以块为单位,存取未对齐的数据可能开始在上一个内存块,结束在另一个内存块。这样中间可能要经过复杂运算在合并在一起,降低了效率。字节对齐后,提高了cpu的访问速率。

内存对齐原则

  • 1: 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在 32 位为4字节,则要从4的整数倍地址开始存储。

  • 2: 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

  • 3: 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍.不足的要补齐。

内存对齐原则描述的那么复杂,搞我心态是吧,必须实例解我疑惑

结构体内存对齐(无嵌套)

对象的本质就是结构体,对象的底层实现是结构体。内存对齐实际上可以看做是结构体内存对齐,只不过系统对实例化的对象进行了内存优化。接下来实例探究下结构体内存对齐

struct LWStruct1{     double  a; // 8     int     b; // 4     short   c; // 2     char    d; // 1 }LWStruct1;  struct LWStruct2{     double  a; // 8     char    d; // 1     int     b; // 4     short   c; // 2 }LWStruct2;  int main(int argc, char * argv[]) {     @autoreleasepool {         NSLog(@"-----%lu-----%lu",sizeof(LWStruct1),sizeof(LWStruct2));     }     return 0; }  2021-06-08 15:02:54.392903+0800 alignStyle[74021:9798038] -----16-----24

结果分析发现 LWStruct1LWStruct2 所包含的变量是一样的,只是位置不一样,但是内存大小不一样,为什么? 这就是结构体内存对齐。

下面就根据内存对齐原则进行简单的计算和分析

LWStruct1内存大小详细过程(min(m,n) m表示当前开始的位置,n表示大小)

  • 变量a: 占8个字节,offert从0开始, min(0,8), 即0 ~ 7 存放a
  • 变量b: 占4个字节,offert从8开始, min(8,4), 即8 ~ 11 存放b
  • 变量c: 占2个字节,offert从12开始,min(12,2),即12 ~ 13存放c
  • 变量d: 占1个字节,offert从14开始,min(14,1),即14存放d

结果显示 LWStruct1 的实际的内存大小是15字节LWStruct1中最大的变量是a占个8 字节。所以LWStruct1的实际内存大小必须是8的整数倍,15不是8的整数倍,向上取整,不足的自动补齐为16字节。最后LWStruct1的内存大小为16字节
LWStruct1解析图如下

iOS 底层之内存对齐

LWStruct2内存大小详细过程

  • 变量a: 占8个字节,offert从0开始,min(0,8), 即0 ~ 7 存放a
  • 变量d: 占1个字节,offert从8开始, min(8,1), 即8 存放d
  • 变量b: 占4个字节,offert从9开始, min(9,4)9 % 4 != 0,继续往后移动直到找到可以整除4的位置 1212 ~ 15 存放b
  • 变量c: 占2个字节,offert从16开始,min(16,2),即16 ~ 17 存放c

结果显示 LWStruct2 的实际的内存大小是18字节LWStruct2中最大的变量是a占个 8 字节。所以LWStruct2的实际内存大小必须是8的整数倍18不是8的整数倍,向上取整,不足的自动补齐为24字节。最后LWStruct2的内存大小为24字节

LWStruct2解析图如下

iOS 底层之内存对齐

结构体中嵌套结构体

 struct LWStruct1{     double  a; // 8     int     b; // 4     short   c; // 2     char    d; // 1 }LWStruct1;   struct LWStruct2{     double  a; // 8     char    d; // 1     int     b; // 4     short   c; // 2  }LWStruct2;  struct LWStruct3{     long    a; // 8     int     b; // 4     short   c; // 2     char    d; // 1     struct LWStruct2 lwStr; }LWStruct3;  int main(int argc, char * argv[]) {     @autoreleasepool {       NSLog(@"-----%lu-----%lu----%lu",sizeof(LWStruct1),sizeof(LWStruct2),sizeof(LWStruct3));     }     return 0; }   2021-06-08 16:28:40.819854+0800 alignStyle[74082:9819949] -----16-----24----40

LWStruct3内存大小详细过程

  • 变量a: 占8个字节,offert从0开始, min(0,8), 即0 ~ 7 存放a
  • 变量b: 占4个字节,offert从8开始, min(8,4), 即8 ~ 11 存放b
  • 变量c: 占2个字节,offert从12开始,min(12,2),即12 ~ 13 存放c
  • 变量d: 占1个字节,offert从14开始,min(14,1),即14 存放d
  • 变量lwStr:lwStr是结构体变量,内存对齐原则结构体成员要从其内部最大元素大小的整数倍地址开始存储。LWStruct2 中的最大的变量占8字节,所以offert从16开始,LWStruct2的内存大小是18字节min(16,18),即18 ~ 33存放 lwStr

结果显示 LWStruct3 的实际的内存大小是34字节LWStruct3中最大的变量是lwStra都是 8 字节。所以LWStruct3的实际内存大小必须是8的整数倍34不是8的整数倍,向上取整,不足的自动补齐为40字节。最后LWStruct3的内存大小为40字节

LWStruct3解析图如下

前言

内存对齐这个词总是环绕在我们耳边,但是真正的含义我们却一知半解,总感觉被迷雾笼罩,今天就探索下内存对齐,把它神秘的面纱揭开。俗话说实践是检验真理的唯一标准,直接上案例。下面打印对象类型的内存大小,对象实际的内存大小和系统分配的内存大小。代码和打印如下:

LWPerson * person =  [LWPerson alloc]; person.name = @"person"; person.age = 18; LWPerson * newPerson;  NSLog(@"对象类型的内存大小--%lu",sizeof(person)); NSLog(@"对象实际的内存大小--%lu",class_getInstanceSize([person class])); NSLog(@"系统分配的内存大小--%lu",malloc_size((__bridge const void *)(person))); NSLog(@"=================="); NSLog(@"对象类型的内存大小--%lu",sizeof(newPerson)); NSLog(@"对象实际的内存大小--%lu",class_getInstanceSize([newPerson  class])); NSLog(@"系统分配的内存大小--%lu",malloc_size((__bridge const void *)(newPerson)));  2021-06-08 11:16:28.097465+0800 alignStyle[73542:9731629] 对象类型的内存大小--8 2021-06-08 11:16:28.097520+0800 alignStyle[73542:9731629] 对象实际的内存大小--24 2021-06-08 11:16:28.097562+0800 alignStyle[73542:9731629] 系统分配的内存大小--32 2021-06-08 11:16:28.097583+0800 alignStyle[73542:9731629] ================== 2021-06-08 11:16:28.097607+0800 alignStyle[73542:9731629] 对象类型的内存大小--8 2021-06-08 11:16:28.097629+0800 alignStyle[73542:9731629] 对象实际的内存大小--0 2021-06-08 11:16:28.097649+0800 alignStyle[73542:9731629] 系统分配的内存大小--0

结果分析:

  • sizeof:对象类型的内存大小,sizeof 是一个操作符号,不是函数。计算的是传进来的数据类型的大小,这个在编译时期就已经确定。所以 sizeof(person)sizeof(newPerson) 都是8字节,因为它们的本质是结构体指针。

  • class_getInstanceSize:对象实际的内存大小,内存大小是由类的成员变量的大小决定。实际上并不是严格意义上的对象的内存的大小,因为内存进行了8字节对齐,核心算法是define WORD_MASK 7UL ((x + WORD_MASK) & ~WORD_MASK。 所以 person 的内存大小是 24 而不是 20newPerson 只是声明了一个变量,并没有开辟内存,所以大小是0

  • malloc_size 系统分配的内存大小是按16字节对齐的方式,即分配的大小是16的倍数 ,不足16的倍数系统会自动填充字节,注意系统的16字节对齐是在实际的内存大小(经过8字节对齐)的基础上。

问题:
class_getInstanceSizemalloc_size 底层做了什么? 你怎么知道
class_getInstanceSize8字节对齐的呢? 而malloc_size16字节对齐的呢?
class_getInstanceSizemalloc_size探索流程会放在文章的结尾。

内存对齐

前言我们发现对象实际的内存大小是8字节对齐,那么到底是怎么对齐的。引出我们的重点内存对齐。

各类型所占字节

在这里整理些基本数据类型在不同系统下的字节大小,方便大家查看。

iOS 底层之内存对齐

需要内存对齐的原因

  • 内存是以字节为基本单位,cpu在存取数据时,是以块为单位存取,并不是以字节为单位存取。频繁存取未对齐的数据,会极大降低cpu的性能。字节对齐后,会减低cpu的存取次数,这种以空间换时间的做法目的降低cpu的开销。

  • cpu存取是以块为单位,存取未对齐的数据可能开始在上一个内存块,结束在另一个内存块。这样中间可能要经过复杂运算在合并在一起,降低了效率。字节对齐后,提高了cpu的访问速率。

内存对齐原则

  • 1: 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在 32 位为4字节,则要从4的整数倍地址开始存储。

  • 2: 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

  • 3: 收尾工作:结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍.不足的要补齐。

内存对齐原则描述的那么复杂,搞我心态是吧,必须实例解我疑惑

结构体内存对齐(无嵌套)

对象的本质就是结构体,对象的底层实现是结构体。内存对齐实际上可以看做是结构体内存对齐,只不过系统对实例化的对象进行了内存优化。接下来实例探究下结构体内存对齐

struct LWStruct1{     double  a; // 8     int     b; // 4     short   c; // 2     char    d; // 1 }LWStruct1;  struct LWStruct2{     double  a; // 8     char    d; // 1     int     b; // 4     short   c; // 2 }LWStruct2;  int main(int argc, char * argv[]) {     @autoreleasepool {         NSLog(@"-----%lu-----%lu",sizeof(LWStruct1),sizeof(LWStruct2));     }     return 0; }  2021-06-08 15:02:54.392903+0800 alignStyle[74021:9798038] -----16-----24

结果分析发现 LWStruct1LWStruct2 所包含的变量是一样的,只是位置不一样,但是内存大小不一样,为什么? 这就是结构体内存对齐。

下面就根据内存对齐原则进行简单的计算和分析

LWStruct1内存大小详细过程(min(m,n) m表示当前开始的位置,n表示大小)

  • 变量a: 占8个字节,offert从0开始, min(0,8), 即0 ~ 7 存放a
  • 变量b: 占4个字节,offert从8开始, min(8,4), 即8 ~ 11 存放b
  • 变量c: 占2个字节,offert从12开始,min(12,2),即12 ~ 13存放c
  • 变量d: 占1个字节,offert从14开始,min(14,1),即14存放d

结果显示 LWStruct1 的实际的内存大小是15字节LWStruct1中最大的变量是a占个8 字节。所以LWStruct1的实际内存大小必须是8的整数倍,15不是8的整数倍,向上取整,不足的自动补齐为16字节。最后LWStruct1的内存大小为16字节
LWStruct1解析图如下

iOS 底层之内存对齐

LWStruct2内存大小详细过程

  • 变量a: 占8个字节,offert从0开始,min(0,8), 即0 ~ 7 存放a
  • 变量d: 占1个字节,offert从8开始, min(8,1), 即8 存放d
  • 变量b: 占4个字节,offert从9开始, min(9,4)9 % 4 != 0,继续往后移动直到找到可以整除4的位置 1212 ~ 15 存放b
  • 变量c: 占2个字节,offert从16开始,min(16,2),即16 ~ 17 存放c

结果显示 LWStruct2 的实际的内存大小是18字节LWStruct2中最大的变量是a占个 8 字节。所以LWStruct2的实际内存大小必须是8的整数倍18不是8的整数倍,向上取整,不足的自动补齐为24字节。最后LWStruct2的内存大小为24字节

LWStruct2解析图如下

iOS 底层之内存对齐

结构体中嵌套结构体

 struct LWStruct1{     double  a; // 8     int     b; // 4     short   c; // 2     char    d; // 1 }LWStruct1;   struct LWStruct2{     double  a; // 8     char    d; // 1     int     b; // 4     short   c; // 2  }LWStruct2;  struct LWStruct3{     long    a; // 8     int     b; // 4     short   c; // 2     char    d; // 1     struct LWStruct2 lwStr; }LWStruct3;  int main(int argc, char * argv[]) {     @autoreleasepool {       NSLog(@"-----%lu-----%lu----%lu",sizeof(LWStruct1),sizeof(LWStruct2),sizeof(LWStruct3));     }     return 0; }   2021-06-08 16:28:40.819854+0800 alignStyle[74082:9819949] -----16-----24----40

LWStruct3内存大小详细过程

  • 变量a: 占8个字节,offert从0开始, min(0,8), 即0 ~ 7 存放a
  • 变量b: 占4个字节,offert从8开始, min(8,4), 即8 ~ 11 存放b
  • 变量c: 占2个字节,offert从12开始,min(12,2),即12 ~ 13 存放c
  • 变量d: 占1个字节,offert从14开始,min(14,1),即14 存放d
  • 变量lwStr:lwStr是结构体变量,内存对齐原则结构体成员要从其内部最大元素大小的整数倍地址开始存储。LWStruct2 中的最大的变量占8字节,所以offert从16开始,LWStruct2的内存大小是18字节min(16,18),即18 ~ 33存放 lwStr

结果显示 LWStruct3 的实际的内存大小是34字节LWStruct3中最大的变量是lwStra都是 8 字节。所以LWStruct3的实际内存大小必须是8的整数倍34不是8的整数倍,向上取整,不足的自动补齐为40字节。最后LWStruct3的内存大小为40字节

LWStruct3解析图如下

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » iOS 底层之内存对齐求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们