【iOS】内存对齐

内存对齐

OC基本数据类型所占字节数对比

注1BOOL在32位机器被定义为char、在64位机器被定义为bool
boolean_t在32位机器被定义为unsigned int、在64位机器被定义为int
NSInteger在32位机器被定义为int、在64位机器被定义为long
NSUInteger在32位机器被定义为unsigned int、在64位机器被定义为unsigned long
CGFloat在32位机器被定义为float、在64位机器被定义为double

以上多变的情况是是使用宏定义实现的,编译后可查看其实现

注2:由于C语言只会将bool的非0值置为1,因此,BOOL的使用过程中应注意在32位机器上并非只有1和0两种可能取值,取值范围是-128~127(其实也不用太在意,因为现在几乎没几个人还在用32位的手机)

内存对齐规则

  1. 数据成员对⻬规则
    结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int为4字节,则要从4的整数倍地址开始存储
  2. 结构体作为成员
    如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储,(struct a里存有struct b,b里有cha,int,double等元素,那b应该从8的整数倍开始存储)
  3. 收尾工作
    结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补⻬

先有下面三个结构体:

objectivec 复制代码
struct Struct1 {
    double a;  // 8
    char b;    // 1
    int c;     // 4
    short d;   // 2
} struct1;

struct Struct2 {
    double a;  // 8
    int b;     // 4
    char c;    // 1
    short d;   // 2
} struct2;

struct Struct3 {
    double a;  // 8
    int b;     // 4
    char c;    // 1
    short d;   // 2
    int e;     // 4
    struct Struct1 struc;  // 24
} struct3;

根据上面的内存对齐规则,可计算出struct1所占用的字节数是24,struct2所占用的字节数是16,struct3所占用的字节数是48,通过sizeof也可以验证这些答案

内存对齐原因

性能

内存是以字节为基本单位,cpu在存取数据时,是以块为单位存取,并不是以字节为单位存取。频繁存取未对齐的数据(存取未对齐的数据可能开始在上一个内存块,结束在另一个内存块,中间可能要经过复杂运算在合并在一起,降低了效率 ),会极大降低cpu的性能。字节对齐后,会减低cpu的存取次数,提高了cpu的访问速率,这种以空间换时间的做法目的降低cpu的开销

跨平台

有些硬件平台并不能访问任意地址上的任意数据的,只能处理特定类型的数据,否则会导致硬件层级的错误。

有些CPU(如基于 Alpha,IA-64,MIPS,和 SuperH 体系的)拒绝读取未对齐数据。当一个程序要求这些 CPU 读取未对齐数据时,这时 CPU 会进入异常处理状态并且通知程序不能继续执行。

举个例子,在 ARM,MIPS,和 SH 硬件平台上,当操作系统被要求存取一个未对齐数据时会默认给应用程序抛出硬件异常。所以,如果编译器不进行内存对齐,那在很多平台的上的开发将难以进行。

OC对象内存对齐

在之前的文章中已经了解到OC对象实际上是结构体,结构体成员变量的内存排序遵循内存对齐规则,那么对象属性的内存排序也遵守内存对齐规则

创建一个Person类:

objectivec 复制代码
@interface Person : NSObject

@property (nonatomic, assign)double a;
@property (nonatomic, assign)char b;
@property (nonatomic, assign)int c;
@property (nonatomic, assign)short d;

@end

Person* person = [[Person alloc] init];
person.a = 7.7;
person.b = 's';
person.c = 7;
person.d = 7;
NSLog(@"%zd %zd", class_getInstanceSize([Person class]), malloc_size((__bridge const void *)(person)));  //  24 32

通过输出我们可以看出成员变量所占内存大小是24字节,其中isa要占8个字节,其余成员占16个字节,所以至少需要24字节

操作系统在分配内存时,也会有"内存对齐",所以size是24,malloc_size返回 32,即系统实际分配内存32字节(从内存对齐的角度也可以算出32)

总结

内存对齐可以提高cpu的存取效率同时提升安全性,会有部分内存的浪费,但是系统又会根据数据存储情况进行内存优化,尽可能降低内存浪费,这样即保证了性能又减少了浪费

相关推荐
库奇噜啦呼18 小时前
【iOS】static、const、extern关键字
ios
zzywxc78719 小时前
AI工具全景洞察:从智能编码到模型训练的全链路剖析
人工智能·spring·ios·prompt·ai编程
前端 贾公子20 小时前
《Vuejs设计与实现》第 16 章(解析器) 上
vue.js·flutter·ios
Digitally1 天前
如何将大型音频文件从 iPhone 发送到不同的设备
ios·iphone
吴Wu涛涛涛涛涛Tao1 天前
Flutter 实现「可拖拽评论面板 + 回复输入框 + @高亮」的完整方案
android·flutter·ios
搜狐技术产品小编20232 天前
CAEmitterLayer:iOS 中创建炫酷粒子效果的魔法工具
macos·ios·objective-c·cocoa
00后程序员张2 天前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
咕噜签名分发冰淇淋3 天前
内测分发是什么?
ios
2501_916007473 天前
Transporter App 使用全流程详解:iOS 应用 ipa 上传工具、 uni-app 应用发布指南
android·ios·小程序·https·uni-app·iphone·webview