views:

292

answers:

3

There is a byte at a specific index in a byte string which represents eight flags; one flag per bit in the byte. If a flag is set, its corresponding bit is 1, otherwise its 0. For example, if I've got

b'\x21'

the flags would be

0001 0101    # Three flags are set at indexes 0, 2 and 4
             # and the others are not set

What would be the best way to get each bit value in that byte, so I know whether a particular flag is set or not? (Preferably using bitwise operations)

A: 

Specify bit masks (read about bit masks on Wikipedia):

FLAG_1 = 1  # 0000 0001
FLAG_2 = 2  # 0000 0010
FLAG_3 = 4  # 0000 0100
...

And then use AND to check whether a bit is set (flags contains your byte):

if(flags & FLAG_1) { # bit 0 is set, example: 0001 0101 & 0000 0001 = 0000 0001

}
if(flags & FLAG_2) { # bit 1 is set, example: 0001 0101 & 000 0010 = 0000 0000

}
...

Of course you should name FLAG_1, etc to something meaningful, depending on the context. E.g. ENABLE_BORDER.

Update:
I was confused about your comment which bits are set, but after reading another answer I realized your are counting the bits from the wrong end. Bits are numbered zero based from the right.

Felix Kling
Oh, sorry. I'll edit my question.
A: 

x & 1, x & 2, x & 4, x & 8, etc

if those are >0 then the bit 1,2,3,4, etc is set

oedo
+2  A: 

Typically, the least-significant bit is bit index 0 and the most-significant bit is bit index 7. Using this terminology, we can determine if bit index k is set by taking the bitwise-and with 1 shifted to the left by k. If the bitwise and is non-zero, then that means that index k has a 1; otherwise, index k has a 0. So:

def get_bit(byteval,idx):
    return ((byteval&(1<<idx))!=0);

This will correctly determine the value of bits at indices 0...7 of the byte, going from right-to-left (i.e. the least significant bit to the most significant bit, or equivalently from the 1s place to the 27 = 128 place).

Why it works
I figured I should add an explanation of why it works...

1<<0 is 1 = 0000 0001
1<<1 is 2 = 0000 0010
1<<2 is 4 = 0000 0100

As you can see, 1<<k is equivalent to 2k and contains a 1 at exactly the index we are interested and at no other location. Consequently, the bitwise and with 1<<k will either return 0 or 1<<k; it will be 0 if the bit at the index we are interested in is 0 (because 1 and 0 is 0, and all other bits in 1<<k are zero). If the bit we are interested in is 1, then we get a 1 and a 1 in that position, and a 0 and something else, everywhere else.

Michael Aaron Safyan
Thanks for the informative answer, it makes a lot of sense. And you were actually right, the least significant bit is at index 0 in this case.