位字段

按位运算有多贵?假设一个简单的非位字段结构:

struct foo {
    unsigned x;
    unsigned y;
}
static struct foo my_var;

在以后的一些代码中:

my_var.y = 5;

如果 sizeof (unsigned) == 4,则 x 存储在结构的开头,y 存储在 4 个字节中。生成的汇编代码可能类似于:

loada register1,#myvar     ; get the address of the structure
storei register1[4],#0x05  ; put the value '5' at offset 4, e.g., set y=5

这很简单,因为 x 不与 y 混合。但想象一下用位域重新定义结构:

struct foo {
    unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
    unsigned y : 4;
}

xy 都将分配 4 位,共享一个字节。结构因此占用 1 个字节而不是 8 个。考虑组件现在设置 y,假设它最终在高位半字节中:

loada  register1,#myvar        ; get the address of the structure
loadb  register2,register1[0]  ; get the byte from memory
andb   register2,#0x0f         ; zero out y in the byte, leaving x alone
orb    register2,#0x50         ; put the 5 into the 'y' portion of the byte
stb    register1[0],register2  ; put the modified byte back into memory

如果我们有数千或数百万个这样的结构,这可能是一个很好的权衡,它有助于将内存保留在缓存中或防止交换 - 或者可能使可执行文件变得臃肿,从而恶化这些问题并减慢处理速度。和所有事情一样,要善于判断。

设备驱动程序的使用: 避免使用位字段作为设备驱动程序的巧妙实现策略。比特字段存储布局在编译器之间不一定是一致的,使得这种实现不可移植。对设置值的读取 - 修改 - 写入可能无法执行设备所期望的操作,从而导致意外行为。