写程序就是和逻辑和数据打交道,说的简单一点就是和数据打交道。说到数据,数据的存储当然是很重要的。

  数据存储也是有一定的方法,在平常中,我们会用到int型来存储数据,或者bool型(C语言中没有,char型)来存储表示0,1的flag。有时候想想,如果只是简单的存储true和false的话,对于unsigned char型来说是否过于浪费了?信息论告诉我们,1bit数据就可以表示true和false,为什么不能将其存到1bit中?

  那么,现在,我们开始将数据压缩。

  如果有8个这样的数据,我们可以存在一个char型中,也就是uint8中。

  bit0-bit7,每一个位都可以表示2个信息。那么就可以表示8种完全互不影响的标志。至于要表示什么,完全可以由“规则”来定。

  假设,表示flag的数据很多?该如何做?

  一个简单的方式:如果有n个标志,那么有

  uint8 a[n];

  这里,我们采用另外的一种方式。

  uint8 a[m],其中m = n / 8;

  那么,看到8倍这个数据,是不是一下子节省了很多?

  对数据做计算的时候,”/”(除法)显然是要尽量避免的,虽然说是有那么简单,但是对于CPU来说可就不简单了。所以我们这里采用移位的方式。

  即:m = n >> 3

  那么如何去索引到某一个位呢?

  很显然,用某一个0-7的数据将其存起来。

  所以,去对某一个数据写数据需要两个信息,在第M个数组元素上,要写第X个bit位。很容易的会想到,封装一个函数,第一个参数为第几个数组元素,第二个参数为第几个位,第三个参数写入在该位上要写入的值。

  即:

 1 int func(int a,int b,int c)
 2 {
 3     if(c == 0)
 4     {
 5         gs_arg[a] &= ~(1 << b);
 6     }
 7     if(c == 1)
 8     {
 9         gs_arg[a] |= (1 << b);
10     }
11 }

  以上这种方式,实现起来应该没有什么难度。不过,在对a值计算,对b值限定的时候,都会存在一系列的问题。那么我们何不采用另外的方式来解决这个问题呢?

  对于上面提到的m = n >> 3应该表示没有异议吧。对于追求极致的人来说,为什么要把n的最后3位丢掉,这3位可以表示8个信息啊。

  等等,你说什么?移位丢掉的数据可以表示8个信息,你的意思是可以表示0,1,2,3,4,5,6,7?这个问题是显然的。可以表示。

  等等,我好像想到了什么!这样可以解决一些列的问题,不过也会带来另外的问题。

  是的,可以通过丢弃的3位来表示写入数据的位数。用剩余的位的数据来表示数组的第几个元素。

  那么,可以有如下的函数:

  

int func_md(int a,int b)
{
    int ord;
    int s_bit;

    ord = a >> 3;
    s_bit = a & 0x07;
    s_move = 0x01 << s_bit;

    if(b == 0)
    {
        gs_arg[ord] &= ~s_move;
        //或者gs_arg[ord] &= s_move ^ 0xFF;
    }

    if(b == 1)
    {
        gs_arg[ord] |= s_move;
    }
}

  当然,为了满足很多规范,是需要做一些强制转换的限定的,同时传入的参数也存在一定的类型问题,这个在这里就不再那么规范了,表示意思即可。