当前位置: 首页 > news >正文

iOS - Runtime-isa详解(位域、union(共用体)、位运算)

文章目录

  • iOS - Runtime-isa详解(位域、union(共用体)、位运算)
    • 前言
    • 1. `位域`介绍
      • 1.1 思路
      • 1.2 示例 - 结构体
      • 1.3 示例 - union(共用体)
        • 1.3.1 说明
      • 1.4 结构体 对比 union(共用体)
    • 2. arm64架构对isa的优化
      • 2.1 位域内容
        • nonpointer
        • has_assoc
        • has_cxx_dtor
        • shiftcls
        • magic
        • weakly_referenced
        • deallocating
        • extra_rc
        • has_sidetable_rc
      • 2.2 Class、Meta-Class对象存储位置
    • 3. 拓展
      • 3.1 枚举值设计
      • 3.1.1 案例
      • 3.1.2 原理分析

iOS - Runtime-isa详解(位域、union(共用体)、位运算)

前言

本章主要了解Runtime相关内容,苹果对isa做了哪些优化,位域、union(共用体)又是如何运用的

  • 要想学习Runtime,首先要了解它底层的一些常用数据结构,比如isa指针
  • 在arm64架构之前,isa就是一个普通的指针,存储着ClassMeta-Class对象的内存地址
  • 从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息

1. 位域介绍

利用好位域的话,可以使程序运行高效节省内存,操作系统级别的东西很多都会使用

在IM系统的开发中,就使用了位域来对数据进行优化,后续有时间再抽出案例聊聊。

欢迎点赞,收藏,加关注!,谢谢你!!

1.1 思路

假如ZSXPerson类需要3个BOOL类型的属性,这时候我们通常会直接使用@property声明3个属性,这时候系统会给我们生成 3个_开头的成员变量,3对getset方法,所占据的内存也比较多

思路:BOOL 类型属性值要么 YES 要么 NO,使用字节中的一个(0或者1)其实就能表示一个 BOOL 类型的属性值,一个字节就可以表示8个 BOOL 值

1.2 示例 - 结构体

ZSXPerson.h

@interface ZSXPerson : NSObject- (void)setTall:(BOOL)tall;- (BOOL)isTall;- (void)setRich:(BOOL)rich;- (BOOL)isRich;- (void)setHandsome:(BOOL)handsome;- (BOOL)isHandsome;@end

ZSXPerson.m

@interface ZSXPerson() {struct {char tall: 1;char rich: 1;char handsome: 1;} _tallRichHandsome;
}@end@implementation ZSXPerson- (void)setTall:(BOOL)tall {_tallRichHandsome.tall = tall;
}- (BOOL)isTall {return !!_tallRichHandsome.tall;
}- (void)setRich:(BOOL)rich {_tallRichHandsome.rich = rich;
}- (BOOL)isRich {return !!_tallRichHandsome.rich;
}- (void)setHandsome:(BOOL)handsome {_tallRichHandsome.handsome = handsome;
}- (BOOL)isHandsome {return !!_tallRichHandsome.handsome;
}@end

main.m

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];person.tall = NO;person.rich = YES;person.handsome = YES;NSLog(@"tall:%d  rich:%d  handsome:%d", person.isTall, person.isRich, person.isHandsome);}return 0;
}

运行结果:

1.3 示例 - union(共用体)

ZSXPerson.h

@interface ZSXPerson : NSObject- (void)setTall:(BOOL)tall;- (BOOL)isTall;- (void)setRich:(BOOL)rich;- (BOOL)isRich;- (void)setHandsome:(BOOL)handsome;- (BOOL)isHandsome;@end

ZSXPerson.h.m

#import "ZSXPerson.h"#define ZSXTallMask (1)
#define ZSXRichMask (1 << 1)
#define ZSXHandsomeMask (1 << 2)@interface ZSXPerson() {union {char bits;struct {char tall: 1;char rich: 1;char handsome: 1;};}_tallRichHandsome;
}@end@implementation ZSXPerson- (void)setTall:(BOOL)tall {if (tall) {_tallRichHandsome.bits |= ZSXTallMask;}else {_tallRichHandsome.bits &= ~ZSXTallMask;}
}- (BOOL)isTall {return !!(_tallRichHandsome.bits & ZSXTallMask);
}- (void)setRich:(BOOL)rich {if (rich) {_tallRichHandsome.bits |= ZSXRichMask;}else {_tallRichHandsome.bits &= ~ZSXRichMask;}
}- (BOOL)isRich {return !!(_tallRichHandsome.bits & ZSXRichMask);
}- (void)setHandsome:(BOOL)handsome {if (handsome) {_tallRichHandsome.bits |= ZSXHandsomeMask;}else {_tallRichHandsome.bits &= ~ZSXHandsomeMask;}
}- (BOOL)isHandsome {return !!(_tallRichHandsome.bits & ZSXHandsomeMask);
}@end

main.m

int main(int argc, const char * argv[]) {@autoreleasepool {ZSXPerson *person = [[ZSXPerson alloc] init];person.tall = NO;person.rich = YES;person.handsome = YES;NSLog(@"tall:%d  rich:%d  handsome:%d", person.isTall, person.isRich, person.isHandsome);}return 0;
}

运行结果:

1.3.1 说明

1.4 结构体 对比 union(共用体)

  • 结构体的成员是各自占用各自所需大小
  • 共同体的内存大小取决于其中最大的成员的大小,所有成员共用这块内存

  • 使用共用体实际上还是通过位运算来控制每个属性所占位置
  • 其中的sturct目的是增加可读性,实际上不会影响属性所占位置

2. arm64架构对isa的优化

arm64架构对isa中,使用一个64位的共用体来存储更多的信息,通过位域的概念来表示各个存储的信息的存储位置。其中有33位拿来存储Class、Meta-Class地址值


2.1 位域内容

nonpointer
  • 0,代表普通的指针,存储着Class、Meta-Class对象的内存地址
  • 1,代表优化过,使用位域存储更多的信息
has_assoc
  • 是否有设置过关联对象,如果没有,释放时会更快
has_cxx_dtor
  • 是否有C++的析构函数(.cxx_destruct),如果没有,释放时会更快
shiftcls
  • 存储着Class、Meta-Class对象的内存地址信息
magic
  • 用于在调试时分辨对象是否未完成初始化
weakly_referenced
  • 是否有被弱引用指向过,如果没有,释放时会更快
deallocating
  • 对象是否正在释放
extra_rc
  • 里面存储的值是引用计数器减1
has_sidetable_rc
  • 引用计数器是否过大无法存储在isa中
  • 如果为1,那么引用计数会存储在一个叫SideTable的类的属性中

2.2 Class、Meta-Class对象存储位置

Class、Meta-Class对象存储在shiftcls,从上图可知shiftcls是从第4位开始,连续33

isa的掩码:define ISA_MASK 0x0000000ffffffff8ULL

将掩码转为二进制查看

它表示的就是从第4位开始,连续33位,通过这个掩码,就可以将Class、Meta-Class地址值取出来

Class、Meta-Class地址值后三位永远是 0。因为他的掩码左右边 3位是 0,&运算后一定是 0

3. 拓展

3.1 枚举值设计

在iOS中,系统的一些API可以使用|传入多个枚举值,比如:

self.view.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin;

原理就是使用位域设计枚举值,然后通过位运算来取值

3.1.1 案例

我们也自己来设计一个这样的枚举

定义枚举:

typedef NS_OPTIONS(NSUInteger, ZSXOptions) {ZSXOptions1                 = 1 << 0, // 0b00000001ZSXOptions2                 = 1 << 1, // 0b00000010ZSXOptions3                 = 1 << 2, // 0b00000100ZSXOptions4                 = 1 << 3, // 0b00001000ZSXOptions5                 = 1 << 4, // 0b00010000
};

设置值方法:

- (void)setOptions:(ZSXOptions)options {if (options & ZSXOptions1) {NSLog(@"包含了ZSXOptions1");}if (options & ZSXOptions2) {NSLog(@"包含了ZSXOptions2");}if (options & ZSXOptions3) {NSLog(@"包含了ZSXOptions3");}if (options & ZSXOptions4) {NSLog(@"包含了ZSXOptions4");}if (options & ZSXOptions5) {NSLog(@"包含了ZSXOptions5");}
}

使用:

[self setOptions:ZSXOptions1 | ZSXOptions3 | ZSXOptions5];

打印如下:

此时我们已经实现了一个可以传入多个枚举值的接口

3.1.2 原理分析

/**0b000000010b000001000b00010000----------------- | 运算(设置值)0b000101010b00000001----------------- & 运算(取值)0b00000001    为 true*/

@oubijiexi

相关文章:

iOS - Runtime-isa详解(位域、union(共用体)、位运算)

文章目录 iOS - Runtime-isa详解&#xff08;位域、union&#xff08;共用体&#xff09;、位运算&#xff09;前言1. 位域介绍1.1 思路1.2 示例 - 结构体1.3 示例 - union&#xff08;共用体&#xff09;1.3.1 说明 1.4 结构体 对比 union&#xff08;共用体&#xff09; 2. a…...

使用VSCode搭建Vue 3开发环境

使用VSCode搭建Vue 3开发环境 Vue 3是一种流行的前端JavaScript框架,它提供了响应式的数据绑定和组合式的API。Visual Studio Code(VSCode)是一个轻量级但功能强大的源代码编辑器,支持多种语言开发。本文将引导您完成使用VSCode搭建Vue 3开发环境的步骤。 1. 下载和安装V…...

深度学习中的模型蒸馏技术:实现流程、作用及实践案例

在深度学习领域&#xff0c;模型压缩与部署是一项重要的研究课题&#xff0c;而模型蒸馏便是其中一种有效的方法。 模型蒸馏&#xff08;Model Distillation&#xff09;最初由Hinton等人在2015年提出&#xff0c;其核心思想是通过知识迁移的方式&#xff0c;将一个复杂的大模型…...

Java服务运行在Linux----维护常用命令

想起来哪些再添加上去 查看Java程序进程 jps -l 查出进程后根据pid 查询程序所在目录 pwdx 31313 根据端口查找PID 根据pid杀死程序 kill -p 31313 查看目录下所有包含9527的文件 grep -rn 9527 查看磁盘空间 查找文件名"nginx"文件或模糊查找"*nginx*&quo…...

夜晚水闸3D可视化:科技魔法点亮水利新纪元

在宁静的夜晚&#xff0c;当城市的霓虹灯逐渐暗淡&#xff0c;你是否曾想过&#xff0c;那些默默守护着城市安全的水闸&#xff0c;在科技的魔力下&#xff0c;正焕发出别样的光彩&#xff1f;今天&#xff0c;就让我们一起走进夜晚水闸3D模型&#xff0c;感受科技为水利带来的…...

从零开始的软件开发实战:互联网医院APP搭建详解

今天&#xff0c;笔者将以“从零开始的软件开发实战&#xff1a;互联网医院APP搭建详解”为主题&#xff0c;深入探讨互联网医院APP的开发过程和关键技术。 第一步&#xff1a;需求分析和规划 互联网医院APP的主要功能包括在线挂号、医生预约、医疗咨询、健康档案管理等。我们…...

【深度学习】YOLO检测器的发展历程

YOLO检测器的发展历程 YOLO&#xff08;You Only Look Once&#xff09;检测器是一种流行的实时对象检测系统&#xff0c;以其速度和准确性而闻名。自2016年首次推出以来&#xff0c;YOLO已经成为计算机视觉领域的一个重要里程碑。在本博客中&#xff0c;我们将探讨YOLO检测器…...

C语言--编译和链接

1.翻译环境 计算机能够执行二进制指令&#xff0c;我们的电脑不会直接执行C语言代码&#xff0c;编译器把代码转换成二进制的指令&#xff1b; 我们在VS上面写下printf("hello world");这行代码的时候&#xff0c;经过翻译环境&#xff0c;生成可执行的exe文件&…...

实现使用C#代码完成wifi的切换和连接功能

实现使用C#代码完成wifi的切换和连接功能 代码如下&#xff1a; namespace Wifi连接器 {public partial class Form1 : Form{private List<Wlan.WlanAvailableNetwork> NetWorkList new List<Wlan.WlanAvailableNetwork>();private WlanClient.WlanInterface Wla…...

Mac添加和关闭开机应用

文章目录 mac添加和关闭开机应用添加开机应用删除/查看 mac添加和关闭开机应用 添加开机应用 删除/查看 打开&#xff1a;系统设置–》通用–》登录项–》查看登录时打开列表 选中打开项目&#xff0c;点击“-”符号...

QT QInputDialog弹出消息框用法

使用QInputDialog类的静态方法来弹出对话框获取用户输入&#xff0c;缺点是不能自定义按钮的文字&#xff0c;默认为OK和Cancel&#xff1a; int main(int argc, char *argv[]) {QApplication a(argc, argv);bool isOK;QString text QInputDialog::getText(NULL, "Input …...

Unity3d使用Jenkins自动化打包(Windows)(一)

文章目录 前言一、安装JDK二、安装Jenkins三、Jenkins插件安装和使用基础操作 实战一基础操作 实战二 四、离线安装总结 前言 本篇旨在介绍基础的安装和操作流程&#xff0c;只需完成一次即可。后面的篇章将深入探讨如何利用Jenkins为Unity项目进行打包。 一、安装JDK 1、进入…...

HarmonyOS 应用开发之Want的定义与用途

Want 是一种对象&#xff0c;用于在应用组件之间传递信息。 其中&#xff0c;一种常见的使用场景是作为 startAbility() 方法的参数。例如&#xff0c;当UIAbilityA需要启动UIAbilityB并向UIAbilityB传递一些数据时&#xff0c;可以使用Want作为一个载体&#xff0c;将数据传递…...

enscan自动化主域名信息收集

enscan下载 Releases wgpsec/ENScan_GO (github.com) 能查的分类 实操&#xff1a; 首先打开linux 的虚拟机、 然后把下面这个粘贴到虚拟机中 解压后打开命令行 初始化 ./enscan-0.0.16-linux-amd64 -v 命令参数如下 oppo信息收集 运行下面代码时 先去配置文件把coo…...

分享全栈开发医疗小程序 -带源码课件(课件无解压密码),自行速度保存

课程介绍 分享全栈开发医疗小程序 -带源码课件&#xff08;课件无解压密码&#xff09;&#xff0c;自行速度保存&#xff01;看到好多坛友都在求SpringBoot2.X Vue UniAPP&#xff0c;全栈开发医疗小程序 - 带源码课件&#xff0c;我看了一下&#xff0c;要么链接过期&…...

基于YOLOv8与ByteTrack实现多目标跟踪——算法原理与代码实践

概述 在目标检测中&#xff0c;有许多经算法如Faster RCNN、SSD和YOLO的各种版本&#xff0c;这些算法利用深度学习技术&#xff0c;特别是卷积神经网络&#xff08;CNN&#xff09;&#xff0c;能够高效地在图像中定位和识别不同类别的目标。Faster RCNN是一种基于区域提议的…...

C语言——函数练习程序

1.从终端接收一个数,封装一个函数判断该数是否为素数 #include <stdio.h>int pri(int num) {int i 0;for (i 2; i < num; i){if (num % i 0){return 0;break;}}if (i num-1){return 1;} }int main(void) {int num 0;int ret 0;scanf("%d", &num);…...

ssh 启动 docker 中 app, docker logs 无日志

ssh 启动 app, 标准输出被重定向 ssh 客户端&#xff0c;而不是 docker 容器的标准输出。只需要在启动时把app 标准输出重定向到 docker标准输出。 测试如下&#xff1a; 1.启动 docker docker run -it -p 60022:22 --name test test:v4 bash -c "service ssh restart;…...

WPF---1.入门学习

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;WPF &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xf…...

Vue3 + Vite + TS + Element-Plus + Pinia项目(5)对axios进行封装

1、在src文件夹下新建config文件夹后&#xff0c;新建baseURL.ts文件&#xff0c;用来配置http主链接 2、在src文件夹下新建http文件夹后&#xff0c;新建request.ts文件&#xff0c;内容如下 import axios from "axios" import { ElMessage } from element-plus im…...

【Rust】——编写自动化测试(一)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…...

第十二章 微服务核心(一)

一、Spring Boot 1.1 SpringBoot 构建方式 1.1.1 通过官网自动生成 进入官网&#xff1a;https://spring.io/&#xff0c;点击 Projects --> Spring Framework&#xff1b; 拖动滚动条到中间位置&#xff0c;点击 Spring Initializr 或者直接通过 https://start.spring…...

MySQL索引18连问,谁能顶住

前言 过完这个节&#xff0c;就要进入金银季&#xff0c;准备了 18 道 MySQL 索引题&#xff0c;一定用得上。 作者&#xff1a;感谢每一个支持&#xff1a; github 1. 索引是什么 索引是一种数据结构&#xff0c;用来帮助提升查询和检索数据速度。可以理解为一本书的目录&…...

[flink 实时流基础系列]揭开flink的什么面纱基础一

Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。Flink 能在所有常见集群环境中运行&#xff0c;并能以内存速度和任意规模进行计算。 文章目录 0. 处理无界和有界数据无界流有界流 1. Flink程序和数据流图2. 为什么一定要…...

开放平台 - 互动玩法演进之路

本期作者 1. 背景 随着直播业务和用户规模日益壮大&#xff0c;如何丰富直播间内容、增强直播间内用户互动效果&#xff0c;提升营收数据变得更加关键。为此&#xff0c;直播互动玩法应运而生。通过弹幕、礼物、点赞、大航海等方式&#xff0c;用户可以参与主播的直播内容。B站…...

Linux之进程控制进程终止进程等待进程的程序替换替换函数实现简易shell

文章目录 一、进程创建1.1 fork的使用 二、进程终止2.1 终止是在做什么&#xff1f;2.2 终止的3种情况&&退出码的理解2.3 进程常见退出方法 三、进程等待3.1 为什么要进行进程等待&#xff1f;3.2 取子进程退出信息status3.3 宏WIFEXITED和WEXITSTATUS&#xff08;获取…...

RegSeg 学习笔记(待完善)

论文阅读 解决的问题 引用别的论文的内容 可以用 controlf 寻找想要的内容 PPM 空间金字塔池化改进 SPP / SPPF / SimSPPF / ASPP / RFB / SPPCSPC / SPPFCSPC / SPPELAN &#xfffc; ASPP STDC&#xff1a;short-term dense concatenate module 和 DDRNet SE-ResNeXt …...

Qt中常用宏定义

Qt中常用宏定义 一、Q_DECLARE_PRIVATE(Class)二、Q_DECLARE_PRIVATE_D(Dptr, Class)三、Q_DECLARE_PUBLIC(Class)四、Q_D(Class) 和 Q_Q(Class) 一、Q_DECLARE_PRIVATE(Class) #define Q_DECLARE_PRIVATE(Class) inline Class##Private* d_func() { # 此处的 d_ptr 是属于QOb…...

【计算机网络】第 9 问:四种信道划分介质访问控制?

目录 正文什么是信道划分介质访问控制&#xff1f;什么是多路复用技术&#xff1f;四种信道划分介质访问控制1. 频分多路复用 FDM2. 时分多路复用 TDM3. 波分多路复用 WDM4. 码分多路复用 CDM 正文 什么是信道划分介质访问控制&#xff1f; 信道划分介质访问控制&#xff08;…...

Rust编程(五)终章:查漏补缺

闭包 & 迭代器 闭包&#xff08;Closure&#xff09;通常是指词法闭包&#xff0c;是一个持有外部环境变量的函数。外部环境是指闭包定义时所在的词法作用域。外部环境变量&#xff0c;在函数式编程范式中也被称为自由变量&#xff0c;是指并不是在闭包内定义的变量。将自…...

网站点击量查询/经典软文

导读Distributed Replicated Block Device(DRBD)是一个用软件实现的、无共享的、服务器之间镜像块设备内容的存储复制解决方案。数据镜像&#xff1a;实时、透明、同步&#xff08;所有服务器都成功后返回&#xff09;、异步&#xff08;本地服务器成功后返回&#xff09;。DRB…...

网站建设维护需要作假吗/3322免费域名注册

前期准备是需要安装apache2和tomcat。 Apache的默认端口是80&#xff0c;Tomcat的默认端口是8080。 步骤如下&#xff1a;参考文献:http://7909846.blog.51cto.com/7899846/1333577/ &#xff08;1&#xff09;cd /etc/apache2/mods-available &#xff08;2&#xff09;cp pro…...

自己怎么1做网站/百度营销大学

Rust算法俱乐部 #algo 台湾同胞搞的Rust学习算法的教程 rust-algo.club cnx&#xff1a;用Rust实现的X11状态栏 #x11 cnx rustsim 报告 #5 #rustsim 简要&#xff1a; alga 0.9 和 nalgebra 0.18开始支持复数并且与&#xff03;[no-std]保持兼容nalgebra开始在几何代数上添加对…...

网站开发中效率较高的编程语言/营销型网站推广

1. 图的表示有几种方法&#xff1a; 一是使用邻接矩阵&#xff08;其实就是二维数组&#xff09;表示&#xff0c;二是使用邻接表来表示 &#xff0c;三是使用边集来表示 下面使用邻接表来表示 2. 首先定义一个图的节点&#xff0c;其中包含几个属性&#xff0c;包含图节点…...

大连网页模板建站/百度扫一扫

sql小计汇总 rollup用法实例分析更新时间&#xff1a;2009年06月26日 17:47:28 作者&#xff1a;rollup在oracle ,sql-server里面都有有。这里介绍sql server2005里面的一个使用实例&#xff1a;CREATE TABLE tb(province nvarchar(10),city nvarchar(10),score int)INSERT t…...

长沙法律咨询网站设计开发/seo关键词优化价格

1.git shelve的使用 shelve是idea提供的特有暂存&#xff08;搁置&#xff09;代码的功能。使用场景&#xff1a;当你在一个分支上修改代码后但暂时不想提交&#xff0c;这时你需要切换到另外一个分支上去工作&#xff0c;这时候就需要暂存现在修改的代码。&#xff08;git 提供…...