news 2026/4/23 18:44:08

【iOS】内存对齐原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【iOS】内存对齐原理

【iOS】内存对齐原理

  • 获取内存大小方式
    • sizeof
    • class_getInstanceSize
    • malloc_size
  • 内存对齐规则
    • 内存优化

获取内存大小方式

获取内存大小的方式有三种:

  • sizeof
  • class_getInstanceSize
  • malloc_size

sizeof

sizeof是一个操作符,不是函数。我们一般用于计算类型占用的内存大小,其中可以放基本数据类型、对象、指针。这个在编译器的编译阶段就会确定大小而不是运行时。

  • 对于类似int这样的基本数据类型而言:sizeof获取的就是数据类型占用的内存大小,不同的数据类型所占用的内存大小是不一样的。
  • 对于类似NSObject定义的实际对象而言:其对象类型的本质就是一个结构体的指针(即struct objc_object),因此sizeof(objc)打印的是对象objc的指针大小。
  • 对于指针而言:sizeof打印的就是8,因为一个指针的内存大小就是8。

class_getInstanceSize

这个方法就是alloc源码中的一步流程,是runtime提供的API,用于计算对象实际占用的内存,返回具体的字节数。这个需要依据类的属性而变化,其本质就是获取实例对象中成员变量的内存大小。

malloc_size

这个函数就是用于计算系统实际分配的内存大小,由系统完成。

这里我们通过三个实例验证一下结论:

#import<Foundation/Foundation.h>#import<objc/runtime.h>#import<malloc/malloc.h>#import"LYDPerson.h"intmain(intargc,constchar*argv[]){@autoreleasepool{NSObject*objc=[[NSObject alloc]init];NSLog(@"sizeof:%lu",sizeof(objc));NSLog(@"class_getInstanceSize:%lu",class_getInstanceSize([objc class]));NSLog(@"malloc_size:%lu",malloc_size((__bridgeconstvoid*)(objc)));}return0;}
  • sizeof:sizeof(objc)打印的是对象objc的指针大小,一个指针的内存大小是8,因此sizeof(objc)打印的是8。
  • class_getInstanceSize:该自定义类没有自定义属性,仅仅只是继承自NSObject,因此该类的实例对象实际占用的是内存大小是8,打印了8。
  • malloc_size:根据16字节对齐算法就可得打印了16。

结果如下:

内存对齐规则

数据类型对应的字节数表格如下:

这里通过两个结构体对应的存储情况解释清内存大小的计算逻辑,具体过程不过多赘述:

还有稍微复杂的结构体嵌套结构体的内存存储计算方式:

内存优化

内存优化在iOS中也就是属性重排。从上面的几个实例中,我们发现结构体内存大小与结构体成员 内存大小的顺序有关

  • 如果结构体中的数据成员是根据内存从小到大的顺序定义的:根据内存对齐规则来计算结构体内存大小,需要增加有较大的内存padding(即内存占位),才能满足内存对齐规则,比较浪费内存。
  • 如果结构体中的数据成员是根据内存从大到小的顺序定义的:根据内存对齐规则来计算结构内存大小,我们只需要补齐少量内存padding,即可满足内存对齐规则,这就是iOS中采用的属性重排,即利用空间换时间,将类中的属性进行重排,来达到优化内存的目的

下面用实例说明:

@interfaceLYDPerson:NSObject@property(nonatomic,copy)NSString*name;@property(nonatomic,copy)NSString*nickName;@property(nonatomic,assign)intage;@property(nonatomic,assign)longheight;@property(nonatomic)charc1;@property(nonatomic)charc2;@end

通过地址找到了name和nickName:

然而通过isa指针地址找时,却发现是乱码:

这里无法找到原值就是因为iOS针对age、c1、c2属性进行了内存重排。因为age占4个字节,c1和c2分别占1个,于是按照8字节对齐,不足补齐的存储在同一块内存中。

注意:

  1. char类型的数据读取出来是以ASCII码的形式显示。
  2. 图片中地址为 0x0000000000000000 ,表示person中还有属性未赋值。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 18:43:32

GINav:终极GNSS/INS一体化导航数据处理平台完全指南

GINav&#xff1a;终极GNSS/INS一体化导航数据处理平台完全指南 【免费下载链接】GINav GNSS and GNSS/INS integration algorithms 项目地址: https://gitcode.com/gh_mirrors/gi/GINav 在当今自动驾驶、精准农业和基础设施监测等前沿技术领域&#xff0c;高精度定位已…

作者头像 李华
网站建设 2026/4/23 18:40:04

避开SPI读写W25Q128的三大坑:状态寄存器、页边界与擦除耗时

W25Q128实战避坑指南&#xff1a;状态寄存器、页边界与擦除优化的深度解析 当工程师们第一次将W25Q128这颗128Mbit的SPI Flash芯片接入系统时&#xff0c;往往会被其简单的四线接口所迷惑——看似几行代码就能完成读写操作&#xff0c;却在真实项目中频频遭遇数据丢失、系统卡死…

作者头像 李华
网站建设 2026/4/23 18:39:15

用ADA4530静电计实测高阻信号源:从PH探头模拟到电流测量的完整流程

用ADA4530静电计实测高阻信号源&#xff1a;从PH探头模拟到电流测量的完整流程 在精密电子测量领域&#xff0c;高阻抗信号源的特性分析一直是工程师面临的特殊挑战。当我们面对PH探头、离子传感器或生物电信号这类微弱电流检测场景时&#xff0c;传统测量方法往往束手无策——…

作者头像 李华
网站建设 2026/4/23 18:35:05

FrontPage练习题(6)

FrontPage2000 操作题目如下&#xff0c;单击“回答”按钮&#xff0c;进行测试。考生目录&#xff3c;Paper&#xff3c;fp下有fp.htm文件&#xff0c;完成下列操作。注意&#xff1a;完成后的效果如图fp.jpg所示。将操作结果保存在考生目录下&#xff0c;文件名为fp&#xff…

作者头像 李华