位字段的位数可调

可以用位字段(bitfield)指定一个字段有多少位。例如,可以把结构写成这样:

位字段的位数可调 - 图1

如果你有一连串的位字段,计算机会放在一起,以节省空间,也就是说如果有8个1位的位字段,计算机就会把它们保存在一个字节中。

让我们看看如何巧用位字段。

位字段的位数可调 - 图2

只有出现在同一个结构中,位字段才能节省空间。

如果编译器发现结构中只有一个位字段,还是会把它填充成一个字,这就是为什么位字段总是组合在一起。

 

如何选择位数?

位字段不仅可以用来保存一连串真/假值,还可以用来保存小范围的数字,例如一年中的十二个月。假设想在某个结构中保存月份(0到11的值),就可以用一个4位的位字段来保存,为什么?因为4位可以保存0到15,而3位只能保存0到7。

  1. unsigned int month_no:4;

 

位字段的位数可调 - 图3练习

回到Head First水族馆,工作人员正在对顾客进行满意度调查,你能否利用位字段创建相应的结构?

位字段的位数可调 - 图4

 

位字段的位数可调 - 图5练习解答

回到Head First水族馆,工作人员正在对顾客进行满意度调查,请利用位字段创建相应的结构。

位字段的位数可调 - 图6

 

这里没有蠢问题

问:为什么C语言不支持二进制字面值?

:因为二进制字面值占了很大空间,而且十六进制通常写起来更快。

问:为什么保存一个0到10的值需要4位?

:4位可以保存0到二进制数1111(也就是15)的值,但3位最大只能保存二进制数111(也就是7)。

问:如果我把9放到一个3位的字段中会怎样?

:计算机会保存1,因为9的二进制是1001,所以计算机转换成001。

问:位字段就是为了节省空间的吗?

:不仅仅是为了节省空间,如果需要读取低层的二进制信息,位字段就会非常有用。

问:能举个例子吗?

:比如要读写某类自定义二进制文件。

 

位字段的位数可调 - 图7要点

  • 可以用联合在同一个存储器单元中保存不同数据类型。

  • “指定初始化器”按名设置字段的值。

  • C99标准支持“指定初始化器”,C++不支持。

  • 如果用{花括号}中的值初始化联合,这个值会以第一个字段的类型保存。

  • 你完全可以读取联合中未初始化过的字段,编译器不会干涉。但要小心,因为这么做很有可能会出错。

  • 枚举保存符号。

  • 可以用位字段自定义字段的位数。

  • 位字段应当声明为unsigned int