Comparing a bit to a boolean

To convert any non-zero number to 1 (true), there is an old trick: apply the ! (not) operator twice.

if (!!(flags & AMAZING_FLAG) != doSet){

From a logical point of view, flags & AMAZING_FLAG is only a bit operation masking all other flags. The result is a numerical value.

To receive to a boolean value, you would use a comparison

(flags & AMAZING_FLAG) == AMAZING_FLAG

and can now compare this logical value to doSet.

if (((flags & AMAZING_FLAG) == AMAZING_FLAG) != doSet)

In C there may be abbreviations, because of the implicit conversion rules of numbers to boolean values. So you could also write

if (!(flags & AMAZING_FLAG) == doSet)

to write that more terse. But the former version is better in terms of readability.


You need to convert the bit mask to a boolean statement, which in C is equivalent to values 0 or 1.

  • (flags & AMAZING_FLAG) != 0. The most common way.

  • !!(flags & AMAZING_FLAG). Somewhat common, also OK to use, but a bit cryptic.

  • (bool)(flags & AMAZING_FLAG). Modern C way from C99 and beyond only.

Take any of the above alternatives, then compare it with your boolean using != or ==.


You can create a mask based on doSet value:

#define AMAZING_FLAG_IDX 1
#define AMAZING_FLAG (1u << AMAZING_FLAG_IDX)
...

uint16_t set_mask = doSet << AMAZING_FLAG_IDX;

Now your check can look like this:

setAmazingFlag(bool doSet)
{
    const uint16_t set_mask = doSet << AMAZING_FLAG_IDX;

    if (flags & set_mask) {
        // Really expensive thing
        // Update flags
    }
}

On some architectures, !! may be compiled to a branch and by this, you may have two branches:

  1. Normalisation by !!(expr)
  2. Compare to doSet

The advantage of my proposal is a guaranteed single branch.

Note: make sure you don't introduce undefined behaviour by shifting left by more than 30 (assuming integer is 32 bits). This can be easily achieved by a static_assert(AMAZING_FLAG_IDX < sizeof(int)*CHAR_BIT-1, "Invalid AMAZING_FLAG_IDX");