更改字节中的特定位集

标签 c bit-manipulation bitwise-operators bitmask

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

例如函数接收:

11001011

然后我需要将 MSB 设置为 0,这很简单:

buffer[0] &= ~(1 << 7);

但随后我需要将位 6 到 3(我在这里将 LSB 称为位 0)设置为提供给函数的参数。此参数可以是从 0 到 6 的整数。

重要的是我不应该更改任何其他位。

我尝试过使用 mask 之类的东西,但我惨遭失败。然后作为最后的手段,我像下面那样痛苦地做了。它工作正常......但它很丑并且会生成大量指令,使代码运行缓慢:

    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 总是零,因此在 switch case 之前我喜欢:

//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具有无符号类型,因此移位是无符号的。

注意:此示例是针对占用第 6、5、4、3 位的 4 位字段。 0x78面具是((1 << 4) - 1) << 3 ,即 0xf << 3 . 0xf面具是(1 << 4) - 1 .和移位量,3 , 是字段右侧的位数,即位 2、1 和 0。

关于更改字节中的特定位集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47128112/

相关文章:

c++ - 在 C(也是 C++)中, '&' 运算符如何同时用作地址运算符和按位运算符?由于 C 不支持运算符重载

c - C 中是否可以使用按位运算符生成 x%10(模 10)?

c - stm32函数在 "Standard Library"

c - 在 c 和 mono 之间传递(函数)指针

c++ - 如何对结构进行位操作?

database - Oracle 中的按位异或

c - 交换字节中的位

c - 是否有不需要操作系统和文件系统的嵌入式键值存储实现?

c - 除了不能在任何程序中使用的变量名之外,cdecl 中不允许使用哪些变量名?

java - 位循环移位