iOS 性能優(yōu)化之位域,聯(lián)合體,位運(yùn)算的使用,節(jié)省空間

iOS 性能優(yōu)化之位域,共用體,位運(yùn)算的使用,節(jié)省空間

1. 位運(yùn)算方法


@interface Person()
{
    struct  {
        // 位域名 : 位域長
        char tall : 1;// 是否高
        char rich : 1; // 是否富有
        char humor : 1; // 是否幽默
    } myself;
    
    char _my;
}
@end
@implementation Person
-(void)setRich:(BOOL)rich{
    if (rich) {
        _my |= RICH;
    } else {
        _my &= ~RICH;
    }

}
-(void)setTall:(BOOL)tall{
    if (tall) {
        _my |= TALL;
    } else {
        _my &= ~TALL;
    }
}
-(void)setHumor:(BOOL)humor{
    if (humor) {
        _my |= HUMOR;
    } else {
        _my &= ~HUMOR;
    }
}
-(BOOL)tall{
    BOOL ret = _my & TALL;
    return ret;
}
-(BOOL)rich{
    BOOL ret = _my & RICH;
    return ret;
}
-(BOOL)humor{
    BOOL ret = _my & HUMOR;
    return ret;
}

#define TALL (1 << 0)
#define RICH (1 << 1)
#define HUMOR (1 << 2)

測試代碼

- (void)testStruct{
    Person *per = [[Person alloc] init];
    per.tall = YES;
    per.rich = NO;
    per.humor = YES;
    NSLog(@"tall : %d , rich : %d , humor : %d",per.tall,per.rich,per.humor);
}

我們是利用了一個(gè) char 一個(gè)字節(jié)的空間的后三位,因?yàn)槲覀兠看卧O(shè)置值得時(shí)候,都會(huì)去和一個(gè)宏定義做位運(yùn)算,而這三個(gè)宏定義,其實(shí)就是用到了一個(gè)字節(jié)的后三位,分別來存儲(chǔ)不同的值,然后將后三位置為0或者1.

2. 位域

@interface Person()
{
    struct  {
        // 位域名 : 位域長
        char tall : 1;// 是否高
        char rich : 1; // 是否有錢
        char humor : 1; // 是否幽默
    } myself;
    
    char _my;
}
@end
@implementation Person

-(void)setRich:(BOOL)rich{
    myself.rich = rich;

}
-(void)setTall:(BOOL)tall{
    myself.tall = tall;
}
-(void)setHumor:(BOOL)humor{
    myself.humor = humor;
}
-(BOOL)tall{
    BOOL ret = myself.tall;
    return ret;
}
-(BOOL)rich{
    BOOL ret = myself.rich;
    return ret;
}
-(BOOL)humor{
    BOOL ret = myself.humor;
    return ret;
}

這里其實(shí)只占用了一個(gè)字節(jié),用到了其中的三位而已,,也就是 0000 0111 ,后面的三位用來存儲(chǔ)我們的三個(gè)值,

測試代碼


 Person *per = [[Person alloc] init];
    per.tall = YES;
    per.rich = NO;
    per.humor = YES;
    NSLog(@"tall : %d , rich : %d , humor : %d",per.tall,per.rich,per.humor);

我們通過斷點(diǎn),來查看我們的 myself 結(jié)構(gòu)體的值

p/x &(per->myself) - > ((anonymous struct) *) $0 = 0x0000600002b2ae48,然后查看這個(gè)地址的值 x 0x0000600002b2ae48 - > 0x600002b2ae48: 05 00 00 00 00 00 00 00 00 00 00 00 00

可以看到 05,也就是 0000 0101,也就是我們的第一位和第三位為1,和我們設(shè)置的值是一樣的,由此可以證明,我們使用了一個(gè)字節(jié)中的三位,我們再來看下這個(gè)結(jié)構(gòu)體的具體存儲(chǔ)內(nèi)容

p/x per->myself
((anonymous struct)) $0 = (tall = 0x01, rich = 0x00, humor = 0x01)

這次是不是一目了然。

如果發(fā)現(xiàn)打印為-1,是因?yàn)槲覀冊O(shè)置為1位,當(dāng)要補(bǔ)足8位的時(shí)候,其余都補(bǔ)1,所以為 1111 1111 , 所以直接在get方法返回的時(shí)候 添加 !! , 也就是兩個(gè)嘆號(hào)就可以了,強(qiáng)制轉(zhuǎn)化為 bool 類型

3. 聯(lián)合體使用

繼續(xù)上代碼


#define TALL (1 << 0)
#define RICH (1 << 1)
#define HUMOR (1 << 2)
@interface Person()
{
    struct  {
        // 位域名 : 位域長
        char tall : 1;// 是否高
        char rich : 1; // 是否富有
        char humor : 1; // 是否幽默
    } myself;
    
//    char _my;
    
    union {
        
        char bits;
        
        // 增加代碼的可讀性,相對于這個(gè)聯(lián)合體就是說這一個(gè)字節(jié)的各個(gè)位都是做什么用的,占用幾位,總共是用一個(gè)字節(jié)而已
        struct {
            // 位域名 : 位域長
            char tall : 1;// 是否高
            char rich : 1; // 是否富有
            char humor : 1; // 是否幽默
        } my;
        
    } myUnion;
}
@end
@implementation Person

-(void)setRich:(BOOL)rich{
    if (rich) {
        myUnion.bits  |= RICH;
    } else {
        myUnion.bits  &= ~RICH;
    }

}
-(void)setTall:(BOOL)tall{
    if (tall) {
        myUnion.bits  |= TALL;
    } else {
        myUnion.bits  &= ~TALL;
    }
}
-(void)setHumor:(BOOL)humor{
    if (humor) {
        myUnion.bits  |= HUMOR;
    } else {
        myUnion.bits  &= ~HUMOR;
    }
}
-(BOOL)tall{
    BOOL ret = myUnion.bits  & TALL;
    return ret;
}
-(BOOL)rich{
    BOOL ret = myUnion.bits  & RICH;
    return ret;
}
-(BOOL)humor{
    BOOL ret = myUnion.bits  & HUMOR;
    return ret;
}

聯(lián)合體


1. 聯(lián)合體中可以定義多個(gè)成員,聯(lián)合體的大小由最大的成員大小決定
2. 聯(lián)合體的成員公用一個(gè)內(nèi)存,一次只能使用一個(gè)成員
3. 對某一個(gè)成員賦值,會(huì)覆蓋其他成員的值
4. 存儲(chǔ)效率更高,可讀性更強(qiáng),可以提高代碼的可讀性,可以使用位運(yùn)算提高數(shù)據(jù)的存儲(chǔ)效率


其實(shí)這個(gè) 聯(lián)合體 就是占用一個(gè)字節(jié) ,然后聯(lián)合體中可以有多個(gè)成員,但是他們是公用一塊內(nèi)存,第一個(gè)bits使我們真正用的,第二個(gè)定義的結(jié)構(gòu)體就是為了解釋這一個(gè)字節(jié)是干嘛用的,各個(gè)位是干嘛的,上面的代碼我們再打印一下存儲(chǔ)

p/x per->myUnion
((anonymous union)) $0 = {
  bits = 0x05
  my = (tall = 0x01, rich = 0x00, humor = 0x01)
}

可以看到 一目了然,下面的 my 結(jié)構(gòu)體其實(shí)就是對 bits 的解釋,我們設(shè)置了bits 的每一位的值,同時(shí)也是對應(yīng)這個(gè)結(jié)構(gòu)體里面的每一位,因?yàn)樗麄兪枪灿皿w。 0x05 就是 0x0000 0101 ,也就是第一位和第三位為1,my = (tall = 0x01, rich = 0x00, humor = 0x01) 這個(gè)不正是告訴我們 每一位是0還是1嗎?

所以 上面的代碼你甚至可以這么寫


-(void)setRich:(BOOL)rich{
    myUnion.my.rich  = rich;
}
-(void)setTall:(BOOL)tall{
    myUnion.my.tall  = tall;
  
}
-(void)setHumor:(BOOL)humor{

    myUnion.my.humor = humor;
  
}
-(BOOL)tall{
    BOOL ret = myUnion.bits  & TALL;
    return ret;
}
-(BOOL)rich{
    BOOL ret = myUnion.bits  & RICH;
    return ret;
}
-(BOOL)humor{
    BOOL ret = myUnion.bits  & HUMOR;
    return ret;
}

或者這么寫


-(void)setRich:(BOOL)rich{
    myUnion.my.rich  = rich;
}
-(void)setTall:(BOOL)tall{
    myUnion.my.tall  = tall;
  
}
-(void)setHumor:(BOOL)humor{

    myUnion.my.humor = humor;
  
}
-(BOOL)tall{
    BOOL ret = myUnion.bits  & TALL;
    return ret;
}
-(BOOL)rich{
    BOOL ret = myUnion.bits  & RICH;
    return ret;
}
-(BOOL)humor{
    BOOL ret = myUnion.bits  & HUMOR;
    return ret;
}


或者這樣



-(void)setRich:(BOOL)rich{
    myUnion.my.rich  = rich;
}
-(void)setTall:(BOOL)tall{
    myUnion.my.tall  = tall;
  
}
-(void)setHumor:(BOOL)humor{

    myUnion.my.humor = humor;
  
}
-(BOOL)tall{
    BOOL ret = myUnion.my.tall;
    return ret;
}
-(BOOL)rich{
    BOOL ret = myUnion.my.rich;
    return ret;
}
-(BOOL)humor{
    BOOL ret = myUnion.my.humor;
    return ret;
}

都是可以的,因?yàn)樗麄兪且粋€(gè)公用體,都是一樣的道理,是不是覺得很有意思?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容