更改字节中的特定位组
我正在处理一个接收字节的函数,需要更改该字节中的一些位。
例如,该函数接收:
11001011
然后我需要将MSB设置为0,这很容易:
buffer[0] &= ~(1 << 7);
但是我需要将第6位到第3位(我在这里将LSB称为位0)设置为提供给函数的参数。 该参数可以是0到6之间的整数。
重要的是我不应该改变任何其他位。
我试着掩盖和东西,但我失败了。 然后作为最后的手段,我在下面痛苦地做了。 它工作正常…但它很丑陋,并产生大量的指令,使代码运行缓慢:
switch(regAddress) { case 0: buffer[0] &= ~(1 << 5); buffer[0] &= ~(1 << 4); buffer[0] &= ~(1 << 3); break; case 1: buffer[0] &= ~(1 << 5); buffer[0] &= ~(1 << 4); buffer[0] |= (1 << 3); break; //YOU GOT THE IDEA!!..... }
请让我知道在一行(或两行)代码中这样做,所以我可以学习这个技巧。
我犯了一个错误,传递的参数总是0到6,所以我想设置的4位的MSB总是为零,因此在切换情况之前我确实喜欢:
//because we only have 7 address, we already set the 4th bit to 0 buffer[0] &= ~(1 << 6);
如果你有一个位字段,比如第6位到第3位(总共四位),打包成值w
(某种类型的无符号整数),那么你可以使用值v
设置字段:
w = (w & ~0x78) | (v << 3);
这假设v
在要求的范围内。 如果没有,您可以使用(v & 0xf)
代替v
。 掩码操作w & ~0x78
清除位6到3,移位操作将v
移动到适当的位置,并且按位或操作组合它们。
要从w
提取字段,您可以使用:
(w >> 3) & 0xf
移位操作右对齐字段,掩码操作清除字段外的位。 这相当于:
(w & 0x78) >> 3
此版本在移位之前屏蔽该字段(因此它使用更大的掩码值)。
确保w
具有无符号类型,以便移位无符号。
注意:此示例适用于占用位0x78
的4位字段0x78
掩码为((1 << 4) - 1) << 3
,即0xf << 3
。 0xf
掩码是(1 << 4) - 1
。 并且移位量3
是该字段右侧的比特数,即比特2,1和0。
为什么不循环这些位?
def setBits(i, bits): for bit in bits: i |= 1 << bit return i print(bin(setBits(0b11001011, [3, 4, 5, 6])))