欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Class中的isa指针本质

程序员文章站 2024-03-23 21:14:34
...

1.iOS存储优化

BOOL类型占1字节,如何将多个BOOL类型数据存储在一个字节中?可以用一字节的每一位表示一个BOOL类型

  1. 实现原理

#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
};

Class中的isa指针本质 shiftcls才是真正的类对象地址,同理类对象指向元类对象也是这样。

class_rw_t也是通过class_data_bits bits共同体经过位运算获取到的。

相关标签: iOS