Class中的isa指针本质
程序员文章站
2024-03-23 21:14:34
...
1.iOS存储优化
BOOL类型占1字节,如何将多个BOOL类型数据存储在一个字节中?可以用一字节的每一位表示一个BOOL类型
- 实现原理
#import "Person.h"
#define TallMask (1<<0) //表示1左移一位:0b 0000 0001
#define RichMask (1<<1) //表示1左移一位:0b 0000 0010
#define HandsomeMask (1<<2) //表示1左移一位:0b 0000 0100
@interface Person()
{
char _savePersonInfo;
}
@end
@implementation MJPerson
-(instancetype)init{
if (self = [super init]) {
//用一个字节来存储三个变量:从最右往左依次为Tall、Rich、Handsome
_savePersonInfo = 0b00000101;
}
return self;
}
/*思路
0000 0000(_saveBox)
|0000 0001(掩码)
---------
0000 0001(赋值tall为1)
0000 0000
&1111 1110(掩码取反)
---------
0000 0000(赋值tall为0)
1.如果赋的值为1,则按位或;
2.如果赋的值为0,则掩码先取反,后按位与
*/
-(void)setTall:(BOOL)tall{
if (tall) {
//直接或运算
_savePersonInfo |=TallMask;
}else{
//掩码取反再与运算
_savePersonInfo &= ~TallMask;
}
}
-(void)setRich:(BOOL)rich{
if (rich) {
_savePersonInfo |= rich;
}else{
_savePersonInfo &= ~rich;
}
}
-(void)setHandsome:(BOOL)handsome{
if (handsome) {
_savePersonInfo |= handsome;
}else{
_savePersonInfo &= ~handsome;
}
}
/*思路
0000 0101
&0000 0001
---------
0000 0001(取出tall值)
1.按位与,用掩码取出_saveBox中特定位;
2.结果>=1,取反为0,再取反为1;同理,为0则双取反后为0;
*/
-(BOOL)tall{
return !!(_savePersonInfo & TallMask);
}
-(BOOL)rich{
return !!(_savePersonInfo & RichMask);
}
-(BOOL)handsome{
return !!(_savePersonInfo & HandsomeMask);
}
@end
2.代码优化,结构体支持位域,用结构体来替换实现
@interface Person()
{
struct{
char tall :1;//声明用一位来存储,并且从右至左来存,也可以char tall :3;来声明用3位存储
char rich :1;
char handsome :1;
}_tallRichHandsome;
}
@end
@implementation Person
-(instancetype)init{
if (self = [super init]) {
//用一个字节来存储三个变量:从最右往左依次为Tall、Rich、Handsome
_savePersonInfo = 0b00000101;
}
return self;
}
-(void)setTall:(BOOL)tall{
_tallRichHandsome.tall = tall;
}
-(void)setRich:(BOOL)rich{
_tallRichHandsome.rich = rich;
}
-(void)setHandsome:(BOOL)handsome{
_tallRichHandsome.handsome = handsome;
}
-(BOOL)tall{
return !!_tallRichHandsome.tall;//非0(包括负数)取反为0
}
-(BOOL)rich{
return !!_tallRichHandsome.rich;//非0(包括负数)取反为0
}
-(BOOL)handsome{
return !!_tallRichHandsome.handsome;//非0(包括负数)取反为0
}
3.代码优化,用共同体可以同时用以上两种方式来写
union{
char bits;
//这个结构体只是一个摆设,增加可读性(但是也可以直接_tallRichHandsome.tall来使用)
struct{
char tall :1;//声明用一位来存储,并且从右至左来存
char rich :1;
char handsome :1;
};
}_tallRichHandsome;
总结:回归到实例对象的底层结构中,打印isa指针本来应该是类对象的地址,但是并不是,这事因为isa是一个共同体,需要进行位运算才能获取到真正的类对象地址。
union isa_t
{
isa_t() { }
isa_t(uintptr_t value) : bits(value) { }
Class cls;
uintptr_t bits;
#if SUPPORT_PACKED_ISA
// extra_rc must be the MSB-most field (so it matches carry/overflow flags)
// nonpointer must be the LSB (fixme or get rid of it)
// shiftcls must occupy the same bits that a real class pointer would
// bits + RC_ONE is equivalent to extra_rc + 1
// RC_HALF is the high bit of extra_rc (i.e. half of its range)
// future expansion:
// uintptr_t fast_rr : 1; // no r/r overrides
// uintptr_t lock : 2; // lock for atomic property, @synch
// uintptr_t extraBytes : 1; // allocated with extra bytes
# if __arm64__
# define ISA_MASK 0x0000000ffffffff8ULL
# define ISA_MAGIC_MASK 0x000003f000000001ULL
# define ISA_MAGIC_VALUE 0x000001a000000001ULL
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 19;
# define RC_ONE (1ULL<<45)
# define RC_HALF (1ULL<<18)
};
# elif __x86_64__
# define ISA_MASK 0x00007ffffffffff8ULL
# define ISA_MAGIC_MASK 0x001f800000000001ULL
# define ISA_MAGIC_VALUE 0x001d800000000001ULL
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t has_cxx_dtor : 1;
uintptr_t shiftcls : 44; // MACH_VM_MAX_ADDRESS 0x7fffffe00000
uintptr_t magic : 6;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 8;
# define RC_ONE (1ULL<<56)
# define RC_HALF (1ULL<<7)
};
# else
# error unknown architecture for packed isa
# endif
// SUPPORT_PACKED_ISA
#endif
#if SUPPORT_INDEXED_ISA
# if __ARM_ARCH_7K__ >= 2
# define ISA_INDEX_IS_NPI 1
# define ISA_INDEX_MASK 0x0001FFFC
# define ISA_INDEX_SHIFT 2
# define ISA_INDEX_BITS 15
# define ISA_INDEX_COUNT (1 << ISA_INDEX_BITS)
# define ISA_INDEX_MAGIC_MASK 0x001E0001
# define ISA_INDEX_MAGIC_VALUE 0x001C0001
struct {
uintptr_t nonpointer : 1;
uintptr_t has_assoc : 1;
uintptr_t indexcls : 15;
uintptr_t magic : 4;
uintptr_t has_cxx_dtor : 1;
uintptr_t weakly_referenced : 1;
uintptr_t deallocating : 1;
uintptr_t has_sidetable_rc : 1;
uintptr_t extra_rc : 7;
# define RC_ONE (1ULL<<25)
# define RC_HALF (1ULL<<6)
};
# else
# error unknown architecture for indexed isa
# endif
// SUPPORT_INDEXED_ISA
#endif
};
shiftcls才是真正的类对象地址,同理类对象指向元类对象也是这样。
class_rw_t也是通过class_data_bits bits共同体经过位运算获取到的。
上一篇: linux中进程管理
下一篇: MAC系统下 Flutter 环境配置
推荐阅读
-
Class中的isa指针本质
-
关于MFC中AfxGetApp函数是怎么得到全局对象的指针的简要分析
-
java中实现反射,以及利用反射实现调用已知class文件的方法和属性。
-
Angular中ng-class更新后,class不随着马上更新的问题解决 博客分类: Angular.js ng-classngclassclassangular更新
-
图文详解Java中class的初始化顺序
-
图文详解Java中class的初始化顺序
-
使用java web 在jsp文件及Class中连接MySQL和SQLsever 的驱动方法
-
php正则删除html代码中class样式属性的方法 原创
-
使用java web 在jsp文件及Class中连接MySQL和SQLsever 的驱动方法
-
深入解析Java中的Class Loader类加载器