C 语言 —— 位字段

操作位的方法除了位运算符之外,第2种方法是位字段。位字段是一个 signed int 或 unsigned int 类型变量中的一组相邻的位。C99 和 C11 新增了 _Bool 类型的位字段。
位字段通过一个结构声明来建立,该结构声明为每个字段提供标签,并确定该字段的宽度。

struct { 
    unsigned int autfd : 1; 
    unsigned int bldfc : 1; 
    unsigned int undln : 1; 
    unsigned int itals : 1; 
} prnt;

根据该声明,prnt 包含4个1位的字段。现在,可以通过普通的结构成员运算符(.)单独给这些字段赋值:

prnt.itals = 0; 
prnt.undln = 1;

由于每个字段恰好为1位,所以只能为其赋值1或0。变量 prnt 被储存在一个 int 大小的内存单元中,但是在本例中只使用了其中的4位。

带有位字段的结构提供一种记录设置的方便途径。许多设置就是简单的二选一。例如,开或关、真或假、字体的粗体或斜。如果只需要使用 1 位,就不需要使用整个变量。内含位字段的结构允许在一个存储单元中储存多个设置。有时,某些设置也有多个选择,因此需要多位来表示。这没问题,字段不限制 1 位大小。

struct { 
    unsigned int code1 : 2; 
    unsigned int code2 : 2; 
    unsigned int code3 : 8; 
} prcode;

以上代码创建了两个2位的字段和一个8位的字段。可以这样赋值:

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

但是,要确保所赋的值不超出字段可容纳的范围。

如果声明的总位数超过了一个 unsigned int 类型的大小会怎样
会用到下一个 unsigned int 类型的存储位置。一个字段不允许跨越两个 unsigned int 之间的边界。编译器会自动移动跨界的字段,保持 unsigned int 的边界对齐。一旦发生这种情况,第1个 unsigned int 中会留下一个未命名的“洞”。 可以用未命名的字段宽度“填充”未命名的“洞”使用一个宽度为 0 的未命名字段迫使下一个字段与下一个整数对齐

struct { 
    unsigned int field1 : 1 ; 
    unsigned int : 2 ; 
    unsigned int field2 : 1 ; 
    unsigned int : 0 ; 
    unsigned int field3 : 1 ; 
} stuff; 

这里,在 stuff.field1 和 stuff.field2 之间,有一个 2 位的空隙;stuff.field3 将储存在下一个unsigned int中。

字段储存在一个 int 中的顺序取决于机器。在有些机器上,存储的顺序是从左往右,而在另一些机器上,是从右往左。另外,不同的机器中两个字段边界的位置也有区别。由于这些原因,位字段通常都不容易移植。尽管如此,有些情况却要用到这种不可移植的特性。例如,以特定硬件设备所用的形式储存数据。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值