Checking if a bit is set in a byte

Started by
23 comments, last by Trienco 9 years, 10 months ago
Hi Guys,

Just wondering if there is an easy way to check if a bit is set in a byte.

So, if I wanted to see it bit 5 was set for example?

Thanks in advance smile.png
Advertisement

bool IsBitSet( unsigned char byte, int index )
{
  int mask = 1<<index;
  return (byte & mask) != 0;
}

When you AND two values together, every bit that wasn't 1 in *both* values is set to zero. So if you want to check if a certain bit is set, you AND that one bit to a value, and then see if the result is 0 (the bit wasn't present), or if the result is the same what you AND'd.

if( (10110 & 10000) == 10000 )

if( (value & mask) == mask )

You can drop the " == mask " part because, in C++, non-zero integers automaticly convert to 'true':

if(value & mask) //If the result is 00000, then the statement evaluates to false, otherwise it evaluates to true.

Hodgeman's func does the same thing, but also uses an index to create the mask by shifting the value 00000001 over N places to become (for example) 00010000.

Thanks guys!

I'll give this a try very shortly smile.png

bool IsBitSet( unsigned char byte, int index )
{
  int mask = 1<<index;
  return (byte & index) != 0;
}

I think you meant to use mask and not index in your return statement.

Alternatively:

bool is_bit_set(unsigned char byte, int index) {
  return (byte >> index) & 1;
}

Here is the results I get with Clang 3.3 with -O3:

IsBitSet(unsigned char, int):                          # @IsBitSet(unsigned char, int)
    btl    %esi, %edi
    setb    %al
    ret

is_bit_set(unsigned char, int):                       # @is_bit_set(unsigned char, int)
    btl    %esi, %edi
    setb    %al
    ret

and with GCC 4.9 with -O3:

IsBitSet(unsigned char, int):
    mov    ecx, esi
    mov    eax, 1
    movzx    edi, dil
    sal    eax, cl
    test    eax, edi
    setne    al
    ret
is_bit_set(unsigned char, int):
    movzx    eax, dil
    mov    ecx, esi
    sar    eax, cl
    and    eax, 1
    ret

When you AND two values together, every bit that wasn't 1 in *both* values is set to zero. So if you want to check if a certain bit is set, you AND that one bit to a value, and then see if the result is 0 (the bit wasn't present), or if the result is the same what you AND'd.

if( (10110 & 10000) == 10000 )
if( (value & mask) == mask )

You can drop the " == mask " part because, in C++, non-zero integers automaticly convert to 'true':
if(value & mask) //If the result is 00000, then the statement evaluates to false, otherwise it evaluates to true.


Hodgeman's func does the same thing, but also uses an index to create the mask by shifting the value 00000001 over N places to become (for example) 00010000.


This actually seems to work very well. Easy to understand too smile.png

if( (10110 & 10000) == 10000 )
if( (value & mask) == mask )


I wonder, why do some people write "== mask" instead of "!= 0"? I suppose it doesn't matter much when the variable is "mask" and/or you use a function, but I've seen this pattern with huge blocks of hard-coded if checks with duplicated giant enum names everywhere.

if( (10110 & 10000) == 10000 )
if( (value & mask) == mask )


I wonder, why do some people write "== mask" instead of "!= 0"? I suppose it doesn't matter much when the variable is "mask" and/or you use a function, but I've seen this pattern with huge blocks of hard-coded if checks with duplicated giant enum names everywhere.

Consider what happens if mask contains more than one bit set. Comparing the AND-result against the mask checks if all bits are set, while comparing against 0 checks if any bit is set.

In that case it is not a matter of relative style or convention, but a matter of absolute correctness; one is correct and the other one is wrong.

This topic is closed to new replies.

Advertisement