更改字节中的特定位集

Changing specific set of bits in a byte

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

例如函数接收:

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,所以我要设置的4bits的MSB总是0,所以在switch case之前我喜欢:

//because we only have 7 address, we already set the 4th bit to 0
buffer[0] &= ~(1 << 6);

为什么不遍历这组位?

def setBits(i, bits):
    for bit in bits:
        i |= 1 << bit
    return i

print(bin(setBits(0b11001011, [3, 4, 5, 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 具有无符号类型,以便移位是无符号的。

注:本例为4位字段占用第6、5、4、3位。0x78掩码为((1 << 4) - 1) << 3,即0xf << 30xf 掩码是 (1 << 4) - 1。移位量 3 是字段右侧的位数,即位 2、1 和 0。