Sign in to follow this  
noatom

Checking if a bit is set, when it's not the first

Recommended Posts

noatom    927

If I had:

 

00010101

 

And I wanted to check if the third bit, the one between the other 2 positive ones is positive, should I do a shift to the right, so it becomes the right most 1 bit, then do a shift to the left, so it becomes the left most 1 bit? Then shift, AGAIN, so it goes back to its original position, so i can use & on it?

 

>> 00000101

<< 10000000

>> 00000100

 

What im actually asking is: when the bit you want to check, is between other bits, should I handle it this way?

Edited by noatom

Share this post


Link to post
Share on other sites
noatom    927
bool is_set(uint x, uint bit)
{
  return ((x >> bit) & 0x01);
}

Think thats right smile.png

 

 

Yeah, that makes a hell of a lot more sense than my logic. Thank you 

Share this post


Link to post
Share on other sites
Alberth    9529

Alternatively:

return x & (1 << bit);

Which works by masking everything but that bit and checking if the result is nonzero.

 

I always explicitly compare such expressions against 0 to denote it's a test result rather than a numeric answer:

return (x & (1 << bit)) != 0;

Share this post


Link to post
Share on other sites
Hodgman    51339

Alternatively:

return x & (1 << bit);
Which works by masking everything but that bit and checking if the result is nonzero.

Be careful with the exact types involved. If x is a 64-bit type and you have 32-bit ints, checking bit 40 won't work well with that code, but it'll be fine with the `(x >> bit) & 1' version.
EDIT: Even if x is an unsigned 32-bit integer, I believe checking bit 31 with that code was technically undefined behavior (because of overflow) until C++14.

I've been stung by that 64-bit bug before... sad.png
Upgraded a bunch of types from uint32's to uint64's to pack more fields into my masks, and suddenly half my bitmasks stop working sad.png needed (1ULL << index), (((uint64)1) << index), etc, instead of (1 << index).

On the same topic as edit - right shift is also bullshit (aka "implementation defined") in C++ too. Although I've never used a compiler that doesn't treat right-shift of a signed variable to be arithmetic/sign-extending, and a right-shift of an unsigned variable to be logical/zero-fill.

Share this post


Link to post
Share on other sites
alvaro    21266

On the same topic as edit - right shift is also bullshit (aka "implementation defined") in C++ too. Although I've never used a compiler that doesn't treat right-shift of a signed variable to be arithmetic/sign-extending, and a right-shift of an unsigned variable to be logical/zero-fill.


I have develop two habits that save me a lot of grief:
(1) always use unsigned integer types when doing bitwise manipulations (all these operations are well defined for unsigned types), and
(2) always use literals of the correct type (so 1u if it's an unsigned int, 1ull if it's an unsigned long long, 1.0 if it's a double, etc.).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this