位字段
按位运算有多贵?假设一个简单的非位字段结构:
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;
}
x
和 y
都将分配 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
如果我们有数千或数百万个这样的结构,这可能是一个很好的权衡,它有助于将内存保留在缓存中或防止交换 - 或者可能使可执行文件变得臃肿,从而恶化这些问题并减慢处理速度。和所有事情一样,要善于判断。
设备驱动程序的使用: 避免使用位字段作为设备驱动程序的巧妙实现策略。比特字段存储布局在编译器之间不一定是一致的,使得这种实现不可移植。对设置值的读取 - 修改 - 写入可能无法执行设备所期望的操作,从而导致意外行为。