iOS底层-结构体内存(2)

f9ef09d5e5f9408cabc965e2414e55b6~tplv-k3u1fbpfcp-watermark.image

写在前面: iOS底层原理探究是本人在平时的开发和学习中不断积累的一段进阶之
路的。 记录我的不断探索之旅,希望能有帮助到各位读者朋友。

目录如下:

  1. iOS 底层原理探索之 alloc

以上内容的总结专栏


准备

Objective-C ,通常写作ObjC或OC,是扩充C的面向对象编程语言。它主要适用于Mac OS X 和 GNUstep者两个使用OpenStep标准的系统,而在NeXTSTEP和OpenStep中它更是基本语言。

GCC和Clang含Objective-C的编译器,Objective-C可以在GCC以及Clang运作的系统上编译。

我们平时开发用的Objective-C语言,编译后最终会转化成C/C++语言。

为什么要研究结构体的内存对齐呢? 因为作为一名iOS开发人员,随着对于底层的不断深入探究,我们都知道,所有的对象在底层中都是一个结构体。那么结构体的内存空间又会被系统分配多少空间,这个问题,值得我们一探究竟。

首先,从大神Cooci那里盗取了一张各数据类型占用的空间大小图片,作为今天探究结构体内存对齐原理的依据。

135d5b410b114074ae913ed9b53d2db3~tplv-k3u1fbpfcp-watermark.image

当我们创建一个对象的时候,我们并不需要过多的在意属性的顺序,因为系统会帮我们做优化处理。但是,在创建结构体的时候,就需要我们去分析了,因为这个时候系统并不会帮助我们做优化。

接下来,我们看下面两个结构体:

struct Struct1 {    
    double a;   
    char b;     
    int c;      
    short d;    
    char e;
}struct1;

struct Struct2 {    
    double a;   
    int b;      
    char c;     
    short d;    
    char e;
}struct2;

两个结构体拥有的数据类型是相同的,按照图片中double 是8字节, char 是1字节, int 是4字节,short 是2字节, 那么 两个结构体应该是占 16字节的内存空间,也就是分配16字节空间即可,然而,我们看下面的结果:

    printf("%lu--%lu", sizeof(struct1), sizeof(struct2));
------------
    24--16

那么,这就是有问题的了,两个拥有相同数据类型的结构体,被系统分配到的内存空间是不一样的,这是为什么呢?今天的重点就是这里,结构体的

内存对齐原则:

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

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

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

那么,我们按照以上内存对齐原则再来分析下 struct1 和 struct2 :


struct Struct1 {    /// 18 --> 24
 double a;   //8 [0 1 2 3 4 5 6 7]
 char b;     //1 [8 ]
 int c;      //4 [9 [12 13 14 15]
 short d;    //2 [16 17]
 char e;     //1 [18]
}struct1;


struct Struct2 {    /// 16 --> 16
 double a;   //8 [0 1 2 3 4 5 6 7]
 int b;      //4 [8 9 10 11]
 char c;     //1 [ 12 ]
 short d;    //2 [14 15]
 char e;     // 1 [16]
}struct2;

接着,我们看下下面的结构体

struct Struct3 {    
    double a;           
    int b;              
    char c;             
    short d;            
    int e;              
    struct Struct1 str; 
}struct3;

打印输出结果为 48 ,分析如下:

    double a;           //8 [0 1 2 3 4 5 6 7]
    int b;              //4 [8 9 10 11]
    char c;             //1 [12]
    short d;            //2 [ 14 15 ]
    int e;              //4 [ 16 17 18 19]
    struct Struct1 str; //24 [24 ... 47]

所以,struct3 大小为48。


猜想:内存对齐的收尾工作中的内部最大成员指的是什么的大小呢?

接下来我们来一一验证一下

struct LGStruct4 {          /// 40 --> 48 
    double a;               //8 [0 1 2 3 4 5 6 7]
    int b;                  //4 [8 9 10 11]
    char c;                 //1 [12]
    short d;                //2 [14 15]
    int e;                  //4 [16 17 18 19]
    struct Struct2 str;   //16 [24 ... 39]      
}struct4;

按照我对于内存对齐原则中收尾工作的理解, 最终的大小 应该是 Struct2 的 大小 16 的整数倍 也就是 48 才对。然而, 结果却是:

    NSLog(@"%lu", sizeof(struct4));
--------
    SMObjcBuild[8076:213800] 40

对,是40你没有看错,这样的话,很显然,我理解的就是错误的, 结构体内部最大成员应该指的是这里的 double,那么我们接下来验证一下: 1、

struct Struct2 {    ///16
    double a;   //8 [0 1 2 3 4 5 6 7]
    int b;      //4 [8 9 10 11]
    char c;     //1 [ 12 ]
    short d;    //2 [14 15]
}struct2;

struct LGStruct4 {    /// 24      
    
    short d;  //2 [0 1]              
    
    struct Struct2 str; // 16 [8 ... 23] 

}struct4;

结果是 :24

因为,结构体内部最大成员是 double也就是8;并不是按照 LGStruct4中的str长度为16的整数倍来计算,所以最后的结果是24。

总结

结构体内部最大成员指的是结构体内部的数据类型,所以,结构体内包含结构体的时候,并不是按照内部的结构体长度的整数倍来计算的哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值