C++/C 位段

位段

针对类或结构中unsigned或int成员,C++/C提供了为其指定存储位数的能力,这种成员称为位段。利用位段可用最小的位数来存放数据以更好地利用内存。位段成员必须被声明为unsigned或int类型。(注:目前测试发现,位段仅支持struct,class,以及union,单独出现则编译报错)

实例

 struct BitCard{ 
    unisgned face:4;
    unsigned suit:2;
    unsigned color:1;
 };

包括了3个unsigned型位段:face,suit和color,用于表示一副牌中的一张牌。

声明

声明位段的方式是这样的,在unsigned或int成员后加一冒号,然后再加一个标识位段宽度(即成员被存储的位数)的整形常量。

形如:

struct位结构名{
    数据类型 变量名: 整型常数;
    数据类型 变量名: 整型常数;
} 位结构变量;

其中:
1. 数据类型必须是整型(unsigned或signed)。
2. 整型常数必须是非负的整数, 表示二进制位的个数, 即表示有多少位,且不能超过数据类型的限制。
3. 变量名是选择项, 可以不命名, 这样规定是为了排列需要。

位段宽度必须是在0和存储一个int型值所需位数之间的一个整数常量。前面的结构定义表明face在存储中占4位,成员suit占2位,成员color占1位。这些位数基于每个结构成员取值的范围。成员face存储在0(标识牌A)与12(表示牌K)之间的一个整数,因此需要4位存储在(4位可表示在0到15之间的任一个整数)。成员suit取值范围0到3(0代表方块,1代表红桃,2代表梅花,3代表黑桃),因此只需要2位来存储这个值。成员color要么取值为0,要么为1,因此只需1位来存储。

位结构总长度(位数), 是各个位成员定义的位数之和。 因此 sizeof( struct BitCard )的值为1,占一个字节, 计算方式 (4+2+1)/8+(((4+2+1)%8==0)?0:1)

成员访问

位结构成员的访问与结构成员的访问相同。
例如: 访问上例位结构中的color成员可写成: bc.color
(struct BitCard bc; )

位段的作用

struct info{
    char name[8];
    int age;
    struct addr address;
    float pay;
    unsigned state: 1;
    unsigned pay: 1;
}workers;'

上例的结构定义了关于一个工从的信息。其中有两个位结构成员, 每个位结构成员只有一位, 因此只占一个字节但保存了两个信息, 该字节中第一位表示工人的状态, 第二位表示工资是否已发放。由此可见使用位结构可以节省存贮空间

c++可以指定命名的位段,此时位段在结构中用来作“填充项”。

struct Example{
    unsigned a:13; 
    unsigned  :3;
    unsigned b:4;
};

上面将3位的位段定义为“填充项”,其中不存放任何内容;成员b 成存放于另一个存储单元中。宽度为0的未命名位段通常用于将下一个位段对齐于新的存储单元。

structure Example{
    unsigned a:13;
    unsigned :0;
    unsigned b: 4;
};

用一个未命名的0位位段来跳过a所在存储单元中剩余的位,一边在下一个存储单元中对齐成员b。

位段操作与机器有关。有些机器允许位段跨越字边界,而有些机器不允许不能访问位段中单独的位,位的数组操作符&不能用于位段,它们没有地址位段能节省空间,但它们也会导致编译器生成更慢的机器执行代码。

几个问题

1.

void main()
{
    union
    {
        struct
        {
            unsigned short s1:3;
            unsigned short s2:3;
            unsigned short s3:3;
        }x;
        char c;
    }v;

    v.c=100;
    printf("%d/n",v.x.s3);
}

A:4 B:0 C:3 D:6
答案是A 不过自己电脑运行结果是1

结构struct x,有三个成员s1,s2,s3每一个成员占3 bit,结构与char c union ;
char 一般机器占一个字节(8 bit ,100 二进制值为:01100100,
所以s1后三bit(6,7,8 bit) :100,s2为中间三位(3,4,5 bit)为100 s3为01,所以printf(“%d/n”,v.x.s3)是1,其它是4。现在大多数系统都是小端字节序,而结构体中位域的申明一般是先声明高位。

100 的二进制是 001 100 100

  1. 小端字节序 高高低低
    001—-s3
    100—-s2
    100—-s1
    所以结果应该是 1

  2. 如果先申明的在低位则:
    001—-s1
    100—-s2
    100—-s3
    结果是 4

Reference

[1] 位段 http://www.cnblogs.com/vcyuyan/articles/1730426.html
[2] 位域 http://blog.csdn.net/zhangboyj/article/details/6201856

posted @ 2017-11-20 21:08  cloudren2020  阅读(157)  评论(0编辑  收藏  举报