更改字节中的特定位集
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 << 3
。 0xf
掩码是 (1 << 4) - 1
。移位量 3
是字段右侧的位数,即位 2、1 和 0。
我正在处理接收一个字节并需要更改该字节中的某些位的函数。
例如函数接收:
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 << 3
。 0xf
掩码是 (1 << 4) - 1
。移位量 3
是字段右侧的位数,即位 2、1 和 0。