C/C++ Check If One Bit Is Set In, I.E. Int Variable

C/C++ check if one bit is set in, i.e. int variable

In C, if you want to hide bit manipulation, you can write a macro:

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

and use it this way to check the nth bit from the right end:

CHECK_BIT(temp, n - 1)

In C++, you can use std::bitset.

How to check if exactly one bit is set in an int?

So you want to know if a number is power of 2 or not? Well there is a famous algorithm for that, you can simply do,

check_bit(std::uint32_t bits)
{
return bits && !(bits & (bits-1));
}

Any power of 2 when subtracted by 1 is all 1s. e.g,

4 - 1 = 3 (011)
8 - 1 = 7 (0111)

The bitwise and of any power of 2 and any number 1 less than it will give 0. So we can verify if a number is power of 2 or not by using the expression, n&(n-1).

It will fail when n=0, so we have to add an extra and condition.

For finding the position of bit, you can do:

int findSetBit(std::uint32_t bits)
{
if (!(bits && !(bits & (bits-1))))
return 0;
return log2(bits) + 1;
}

Extra Stuffs

In gcc, you can use __builtin_popcount(), to find the count of set bits in any number.

#include <iostream>

int main()
{
std::cout << __builtin_popcount (4) << "\n";
std::cout << __builtin_popcount (3) << "\n";

return 0;
}

Then check if count is equal to 1 or not.

Regarding count, there is another famous algorithm, Brian Kernighan’s Algorithm. Google it up, it finds count in log(n) time.

Flags - Check if bits are set and only those bits are set

Sometimes the simplest answer eludes you after having your mind wrapped in complicated things.

This is enough:

if(value == flag)

And if you need to check multiple flags:

if(value == (SOMEFLAG_1 | SOMEFLAG_4))
^ ^
important important

And don't forget to enclose the bitwise operations in parenthesis. The precedence is unexpected and without them value == SOMEFLAG_1 would be evaluated first.


And I guess this is a perfect time for preaching for enabling (and paying attention to) compiler warnings:

clang has a very helpful one -Wparentheses which is included in -Wall:

5 : :5:28: warning: | has lower precedence than ==; == will be
evaluated first [-Wparentheses]

if(value == SOMEFLAG_1 | SOMEFLAG_4)
~~~~~~~~~~~~~~~~~~~~^

5 : :5:28: note: place parentheses around the '==' expression
to silence this warning

if(value == SOMEFLAG_1 | SOMEFLAG_4)
^
( )

5 : :5:28: note: place parentheses around the | expression to
evaluate it first

if(value == SOMEFLAG_1 | SOMEFLAG_4)
^
( )

gcc has it also:

5 : :5:14: warning: suggest parentheses around comparison in
operand of '|' [-Wparentheses]

 if(value == SOMEFLAG_1 | SOMEFLAG_4)
~~~~~~^~~~~~~~~~~~~

How do I set, clear, and toggle a single bit?

Setting a bit

Use the bitwise OR operator (|) to set a bit.

number |= 1UL << n;

That will set the nth bit of number. n should be zero, if you want to set the 1st bit and so on upto n-1, if you want to set the nth bit.

Use 1ULL if number is wider than unsigned long; promotion of 1UL << n doesn't happen until after evaluating 1UL << n where it's undefined behaviour to shift by more than the width of a long. The same applies to all the rest of the examples.

Clearing a bit

Use the bitwise AND operator (&) to clear a bit.

number &= ~(1UL << n);

That will clear the nth bit of number. You must invert the bit string with the bitwise NOT operator (~), then AND it.

Toggling a bit

The XOR operator (^) can be used to toggle a bit.

number ^= 1UL << n;

That will toggle the nth bit of number.

Checking a bit

You didn't ask for this, but I might as well add it.

To check a bit, shift the number n to the right, then bitwise AND it:

bit = (number >> n) & 1U;

That will put the value of the nth bit of number into the variable bit.

Changing the nth bit to x

Setting the nth bit to either 1 or 0 can be achieved with the following on a 2's complement C++ implementation:

number ^= (-x ^ number) & (1UL << n);

Bit n will be set if x is 1, and cleared if x is 0. If x has some other value, you get garbage. x = !!x will booleanize it to 0 or 1.

To make this independent of 2's complement negation behaviour (where -1 has all bits set, unlike on a 1's complement or sign/magnitude C++ implementation), use unsigned negation.

number ^= (-(unsigned long)x ^ number) & (1UL << n);

or

unsigned long newbit = !!x;    // Also booleanize to force 0 or 1
number ^= (-newbit ^ number) & (1UL << n);

It's generally a good idea to use unsigned types for portable bit manipulation.

or

number = (number & ~(1UL << n)) | (x << n);

(number & ~(1UL << n)) will clear the nth bit and (x << n) will set the nth bit to x.

It's also generally a good idea to not to copy/paste code in general and so many people use preprocessor macros (like the community wiki answer further down) or some sort of encapsulation.

Test if a bitboard have only one bit set to 1

Sure, it's easy:

int only_one_bit_set_to_one (bboard b)
{
return b && !(b & (b-1));
}

Say b has any bits set, the least significant is bit number k. Then b-1 has the same bits as b for indices above k, a 0-bit in place k and 1-bits in the less significant places, so the bitwise and removes the least significant set bit from b. If b had only one bit set, the result becomes 0, if b had more bits set, the result is nonzero.

Checking the value of a bit in C

  1. Condition (flags & MASK) != 0 checks whether any of the flags's bits specified by MASK are set to 1.

  2. Condition (flags & MASK) == MASK checks whether all of the flags's bits specified by MASK are set to 1.

Symmetrically


  1. Condition (flags & MASK) == 0 checks whether all of the flags's bits specified by MASK are set to 0.

  2. Condition (flags & MASK) != MASK checks whether any of the flags's bits specified by MASK are set to 0.

Choose the one you need in each particular case.

If you need to check just a single bit (i.e. MASK contains only one bit set to 1), then conditons 1 and 2 are equivalent (and conditons 3 and 4 are equivalent as well).

It is not entirely clear from the text you quoted whether MASK can contain more than one bit set to 1.

C/C++ check if one bit is set in, i.e. int variable

In C, if you want to hide bit manipulation, you can write a macro:

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

and use it this way to check the nth bit from the right end:

CHECK_BIT(temp, n - 1)

In C++, you can use std::bitset.

How to check certain bits of a variable in C++?

int bitsToInt(int value, int s, int e) {
int mask = ((1 << (e - s + 1)) - 1) << s;
return (value & mask) >> s;
}

bitsToInt(7, 2, 3) returns 1

thinking about it a bit more, if what you want is to stuff several values into one int you can be better off doing bitfields and have compiler worry about masks and shifts.

How to find the 3rd bit of a number

Checking if a given bit is set is a classic pattern that you will encounter in a great many codebase. So even if there are cleaner ways to do it in modern C++, it's still worth being able to at least recognise the old school pattern when it pops up:

// You will typically see bit masks predefined in constants or an enum.
enum flags {
FEATURE_1 = 1 << 0, // first bit
FEATURE_2 = 1 << 1, // second bit
FEATURE_3 = 1 << 2, // third bit
FEATURE_4 = 1 << 3, // fourth bit
};

if(value & FEATURE_3) {
// the bit is set
}
else {
//the bit is not set
}

Explanation:

(1 << bit_index): This creates a mask. I.E. a value with only the bit we care about set. E.G. 1 << 3 is 0b00001000 as a 8 bit integer.

val & mask: This does a binary AND between the value and the mask, which will be 0 if and only if the bit is not set. Since any non-zero value is a true, we just use the result of the & as condition.

You could also shift the value and compare against 1, but doing it the other way around has the advantage that the mask can often be precomputed during compilation, so the check becomes a simple binary AND at runtime.

Nowadays, it is neater to do so with std::bitset:

// Replace 4 with the number of meaningful bits
// N.B. index is still 0-based. 1 means the second bit.
if(std::bitset<4>(value).test(2)) {
// the bit is set
}
else {
//the bit is not set
}


Related Topics



Leave a reply



Submit