美文网首页
利用共用体union、位域存储Bool状态值

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

作者: 王的for | 来源:发表于2018-10-25 16:28 被阅读0次

    一、利用位域技术存储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值。


    相关文章

      网友评论

          本文标题:利用共用体union、位域存储Bool状态值

          本文链接:https://www.haomeiwen.com/subject/qrlctqtx.html