前言

今天我遇到了之前阅读《C++程序设计》学过的位域,发现当时只是初步懂得了其用法和为什么要使用。 位域还存在很多特性,现在通过代码总结记录。


#include <iostream>

struct Date
{
    unsigned short nWeekDay : 3;  // 0...7
    unsigned short nMonthDay : 6; // 0...31
    unsigned short nMonth : 5;    // 0...12
    unsigned short nYear : 8;     // 0...100
};

struct Foo
{
    char a: 8; // max = 8 bit = 1 Byte warning while exceed max  
    char b: 2; // 2 bit
    int i: 15; // 15 bit
};

struct Foo1
{
    /* data */
    unsigned a: 4; // 4
    unsigned : 0; // 4+28 = 32 bit fill the memory unit, next variable move to next memory unit
    unsigned b: 4; // 4 new memory unit 
    unsigned c: 4; // 4
};

struct Foo2
{
    int i: 8; // 8 bit
    int j: 4; // 4 bit
    double b; // 64 bit the first memory unit out of range, so move to next 
    int a: 3; // the second memort unit out of range, so move to next
}; // total three memory units

int main(int argc, char *argv[])
{
    std::cout << "sizeof(unsigned int) is: " << sizeof(unsigned int) << std::endl;
    std::cout << "sizeof(unsigned short) is: " << sizeof(unsigned short) << std::endl;
    std::cout << "sizeof(struct Date) is: " << sizeof(struct Date) << std::endl;
    std::cout << "sizeof(Date) is: " << sizeof(Date) << std::endl;
    std::cout << "sizeof(Foo) is: " << sizeof(Foo) << std::endl;
    std::cout << "sizeof(Foo1) is: " << sizeof(Foo1) << std::endl;
    std::cout << "sizeof(Foo2) is: " << sizeof(Foo2) << std::endl;
    return 0;
}

特点

  1. 位域可以用于压缩存储,能用1bit的就绝不用2bit
  2. 位域增加处理时间,访问位域成员时需要把位域从它所在的字中分解出来或把值压缩存到位域所在的字位中
  3. 位域一般使用unsigned数据类型
  4. 未指定占用位默认占用所有位数
  5. 位域以数据类型来区分区域,几种数据类型就表示有几个位域段( 未指定占用位除外 )
  6. 同种位域类使用BIT超过该位域数据类型大小后继续占用该位域数据类型大小
  7. 相邻的两个位域字段的类型不同,则各个编译器的具体实现有差异,VC6采取不压缩方式,GCC和Dev-C++都采用压缩方式
  8. 未用完的BIT还是要占用内存空间,使用int类型的其中4位,后面28位仍然占用空间
  9. 位域遵循结构体对齐原则,整个结构体的总大小为最宽基本类型成员大小的整数倍
  10. 取地址操作符&不能应用在位域字段上,无法取得某个BIT的地址
  11. 位域字段不能是类的静态成员
  12. 位域字段在内存中的位置是按照从低位向高位的顺序放置的
  13. 不要在两个位域中间穿插非位域字段

参考

位域的定义和使用

C++位域