更改字节中的特定位组

我正在处理一个接收字节的函数,需要更改该字节中的一些位。

例如,该函数接收:

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 << 30xf掩码是(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])))