问题
I am working on a function that receives a byte and needs to change some of the bits in that byte.
For example, the function receives:
11001011
Then I need to set the MSB to 0, its easy enough:
buffer[0] &= ~(1 << 7);
But then I need to set bits 6 through 3 (I refer LSB as bit 0 here) to an argument that gets supplied to the function. This argument can be an integer from 0 to 6.
The important thing is I should not change any other bits.
I tried with masking and stuff but I failed miserably. Then as last resort I did it painfully like below. It works fine...but it is ugly and generates tons of instructions, making the code run slow:
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!!.....
}
Please let me know hot to do this in one (or two) line of code so I can learn the trick.
I did a mistake, the argument passed is alway 0 to 6, so the MSB of the 4bits that I want to set is always zero, therefore before the switch case I did like:
//because we only have 7 address, we already set the 4th bit to 0
buffer[0] &= ~(1 << 6);
回答1:
If you have a bit field, say bits 6 though 3 (four bits total), packed into a value w
(some type of unsigned integer), then you can set the field with a value v
with:
w = (w & ~0x78) | (v << 3);
This assumes that v
is within the required range. If not, you can use (v & 0xf)
in place of v
. The mask operation w & ~0x78
clears bits 6 through 3, the shift operation moves v
into the proper position, and the bitwise-or operation combines them.
To extract the field from w
, you can use:
(w >> 3) & 0xf
The shift operation right-justifies the field, and the mask operation clears the bits outside of the field. This is equivalent to:
(w & 0x78) >> 3
This version masks the field before shifting (so it uses a larger mask value).
Make sure w
has an unsigned type so that the shifts are unsigned.
Note: This example is for the 4-bit field occupying bits 6, 5, 4, 3. The 0x78
mask is ((1 << 4) - 1) << 3
, i.e. 0xf << 3
. The 0xf
mask is (1 << 4) - 1
. And the shift amount, 3
, is the number of bits to the right of the field, i.e. bits 2, 1, and 0.
回答2:
Why not loop over the set of bits?
def setBits(i, bits):
for bit in bits:
i |= 1 << bit
return i
print(bin(setBits(0b11001011, [3, 4, 5, 6])))
来源:https://stackoverflow.com/questions/47128112/changing-specific-set-of-bits-in-a-byte