位域

位域

“ 位域 “ 或 “ 位段 “(Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。这种数据结构的一个好处是它可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。第二个好处是位段可以很方便的访问一个整数值的部分内容从而可以简化程序源代码。而这种数据结构的缺点在于,位段实现依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的

声明方法

1
2
3
4
struct bit_field_name
{
type member_name : width;
};
1
2
3
4
5
6
7
8
9
10
11
12
struct _PRCODE
{
unsigned int code1: 2;
unsigned int cdde2: 2;
unsigned int code3: 8;
};

struct _PRCODE prcode;

prcode.code1 = 0;
prcode.code2 = 3;
procde.code3 = 102;

赋值时要注意值的大小不能超过位域成员的容量,例如 prcode.code3 为 8 Bits 的位域成员,其容量为 2^8 = 256,即赋值范围应为 [0,255]。

位域的对齐

1
2
3
4
5
6
struct stuff 
{
unsigned int field1: 30;
unsigned int field2: 4;
unsigned int field3: 3;
};

field1 + field2 = 34 Bits,超出 32 Bits, 编译器会将field2移位至下一个 unsigned int 单元存放, stuff.field1 和 stuff.field2 之间会留下一个 2 Bits 的空隙, stuff.field3 紧跟在 stuff.field2 之后,该结构现在大小为 2 * 32 = 64 Bits。

这个空洞可以用之前提到的未命名的位域成员填充,我们也可以使用一个宽度为 0 的未命名位域成员令下一位域成员与下一个整数对齐。 例如:

1
2
3
4
5
6
7
8
struct stuff 
{
unsigned int field1: 30;
unsigned int : 2;
unsigned int field2: 4;
unsigned int : 0;
unsigned int field3: 3;
};

操作

初始化

1
struct stuff s1= {20,8,6};

或者

1
2
3
4
struct stuff s1;
s1.field1 = 20;
s1.field2 = 8;
s1.field3 = 4;

重映射

声明一个 大小为 32 Bits 的位域

1
2
3
4
5
6
struct box {
unsigned int ready: 2;
unsigned int error: 2;
unsigned int command: 4;
unsigned int sector_no: 24;
}b1;

利用重映射将位域归零

1
2
int* p = (int *) &b1;  // 将 "位域结构体的地址" 映射至 "整形(int*) 的地址" 
*p = 0; // 清除 s1,将各成员归零

利用联合 (union) 将 32 Bits 位域重映射至 unsigned int 型。在任意时刻,联合中只能有一个数据成员可以有值。当给联合中某个成员赋值之后,该联合中的其它成员就变成未定义状态了。union的size就是最大的内部组件大小。

1
2
3
4
union u_box {
struct box st_box;
unsigned int ui_box;
};

联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:

  • 默认访问控制符为 public
  • 可以含有构造函数、析构函数
  • 不能含有引用类型的成员
  • 不能继承自其他类,不能作为基类
  • 不能含有虚函数
  • 匿名 union 在定义所在作用域可直接访问 union 成员
  • 匿名 union 不能包含 protected 成员或 private 成员
  • 全局匿名联合必须是静态(static)的
  • Copyrights © 2018-2022 Haojia Zhu
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信