更改字节中的特定位集

时间:2017-11-06 00:28:28

标签: c bit-manipulation bitwise-operators bitmask

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

例如,函数接收:

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);

2 个答案:

答案 0 :(得分:4)

如果你有一个位字段,比如第6位到第3位(总共四位),打包成值w(某种类型的无符号整数),那么你可以设置一个值{{1 with:

v

这假设w = (w & ~0x78) | (v << 3); 在要求的范围内。如果没有,您可以使用v代替(v & 0xf)。屏蔽操作v清除位6到3,移位操作将w & ~0x78移动到正确的位置,按位或操作将它们组合在一起。

要从v中提取字段,您可以使用:

w

移位操作右对齐字段,掩码操作清除字段外的位。这相当于:

(w >> 3) & 0xf

此版本在移位前屏蔽该字段(因此它使用较大的掩码值)。

确保(w & 0x78) >> 3 具有无符号类型,以便移位无符号。

注意:此示例适用于占用位6,5,4,3的4位字段。w掩码为0x78,即((1 << 4) - 1) << 30xf << 3掩码为0xf。移位量(1 << 4) - 1是字段右边的位数,即位2,1和0。

答案 1 :(得分:-2)

为什么不循环遍历这组位?

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

print(bin(setBits(0b11001011, [3, 4, 5, 6])))