利用共用体union、位域存储Bool状态值

2018-10-25  本文已影响0人  王的for

一、利用位域技术存储Bool状态值的方式可以有效的减少内存。

1)位域在结构体中的实践

定义一个匿名结构体 ,结构体占一个字节的内存大小。

struct{

           // 0b0000 0000  一个字节含有8位

            char  old  :1;//最低位(最右边开始) 一个位bit  

            char  tall :1;

            char  fat  :1;

        };

2)由于BOOL的值只有真假两种也就是0,非0因此可以利用这个特性来做位域存储

3)通常情况定义一个Person类,里面三个BOOL属性,old、tall、fat

通常做法如下:定义三个BOOL变量_old、_tall、_fat

- (void)setFat:(BOOL)fat

{

          _fat = fat;

}

        那么这样做,意味着Person对象里面有1个字节存_old数据,一个字节存_tall数据,一个字节存_fat数据。总的需要3个字节来存放三个状态值。而每个字节里面存放的都是0或1,这两个数字在8位里面只需要用到最低位就够了,剩余的6个位是空余的,导致浪费。所以如果三个或者四个熟悉的状态值存储,往往可以利用一个字节三个或者四个位就能存储完成。(这个也是很多底层C语言代码的一种减少内存开销的存储方式)。

4)共用体:union,与struct类似,不同是:里面的内容公用一块内存空间,后面赋值的内容可能完全覆盖之前的其他内容赋值。union的大小取决于内容元素占用最大的那个。

5)结合union构建一个存储三种BOOL状态值的存储。(union的引入增加代码可读性,及代码简便)代码如下:

#import "HPPerson.h"

#define oldMask (1<<0)//位域运算old值的掩码

#define tallMask (1<<1)//位域运算tall值的掩码

#define fatMask (1<<2)//位域运算fat值的掩码

//Mask...

@implementation HPPerson3

{

    //定义一个共用体体(1个字节大小) 利用位域来存储

    union{

        char bits;

        //表示说明作用。增加可读性

        struct{

            char old  :1;//oldMask最低位(最右边开始) 一个位bit

            char tall :1;//tallMask

            char fat  :1;//fatMask

        };

    }_oldTallFat;

}

- (instancetype)init

{

    self= [super init];

    if(self) {

        NSLog(@"union体大小:%lu",sizeof(_oldTallFat));

    }

    return self;

}

/*

 1、取值:&运算

 2、设值:|运算

 */

//=============设值运算========

- (void)setOld:(BOOL)old

{

    if(old) {

        _oldTallFat.bits |= oldMask;

    }else{

        _oldTallFat.bits&= (~oldMask);

    }

}

- (void)setTall:(BOOL)tall

{

    if(tall) {

        _oldTallFat.bits |= tallMask;

    }else{

        _oldTallFat.bits&= (~tallMask);

    }

}

- (void)setFat:(BOOL)fat

{

    if(fat) {

        _oldTallFat.bits |= fatMask;

    }else{

        _oldTallFat.bits&= (~fatMask);

    }

}

//================取值==========

//0假,非0真(-1也是真)

- (BOOL)isOld

{

    return !!(_oldTallFat.bits&oldMask);// !!的使用,可以巧妙转换非0的数值为BOOL值

}

- (BOOL)isFat

{

    return !!(_oldTallFat.bits&fatMask);

}

- (BOOL)isTall

{

    return !!(_oldTallFat.bits&tallMask);

}

@end

6)总结:

1、利用&、|、~的二进制相关运算符,巧妙存取一个字节里存储的值。

2、union的使用好处,增加了可读性代码及以后的扩展。

3、位域存储减少了内存开销。

4、逻辑运算符“!”的使用:!!,可以巧妙转换非0的数值为BOOL值。


上一篇下一篇

猜你喜欢

热点阅读