CBitmasks & Flags

Bitmasks & Flags

A single integer has many bits, and nothing says they all have to represent one number — each bit can instead represent an independent true/false flag. This is a bitmask: a set of boolean flags packed into one integer, combined and tested with bitwise operators instead of an array of separate booleans.

Defining flags with left-shift

The idiomatic way to define a set of flag constants is with 1 << n, so each constant has exactly one bit set, and no two flags accidentally share a bit:

C
#define FLAG_READ    (1 << 0)  // 0001
#define FLAG_WRITE   (1 << 1)  // 0010
#define FLAG_EXECUTE (1 << 2)  // 0100
#define FLAG_HIDDEN  (1 << 3)  // 1000
Combining, checking, and clearing flags

Operation

How

Combine flags

flags = FLAG_READ | FLAG_WRITE;

Add a flag

flags |= FLAG_EXECUTE;

Check if a flag is set

if (flags & FLAG_WRITE) { ... }

Clear a flag

flags &= ~FLAG_HIDDEN;

Toggle a flag

flags ^= FLAG_READ;

Worked example: a permissions system

C
#include <stdio.h>

#define PERM_READ    (1 << 0)
#define PERM_WRITE   (1 << 1)
#define PERM_EXECUTE (1 << 2)

void print_permissions(unsigned int perms) {
    printf("read=%d write=%d execute=%d\n",
           (perms & PERM_READ)    != 0,
           (perms & PERM_WRITE)   != 0,
           (perms & PERM_EXECUTE) != 0);
}

int main(void) {
    // Combine flags with | to build up a permission set.
    unsigned int file_perms = PERM_READ | PERM_WRITE;
    print_permissions(file_perms);

    // Add execute permission.
    file_perms |= PERM_EXECUTE;
    print_permissions(file_perms);

    // Revoke write permission.
    file_perms &= ~PERM_WRITE;
    print_permissions(file_perms);

    // Check a single flag directly.
    if (file_perms & PERM_READ) {
        printf("file is readable\n");
    }

    return 0;
}
read=1 write=1 execute=0
read=1 write=1 execute=1
read=1 write=0 execute=1
file is readable
Why bitmasks instead of an array of booleans

An array of eight bool values (in C, typically stored as one byte each) uses eight bytes to represent eight flags. The same eight flags packed into the bits of a single unsigned char use exactly one byte — an 8x reduction. At larger scale (thousands or millions of flag sets, as in permission systems, feature flags, or network protocol headers) this adds up to a meaningful difference in memory use, and it also lets you combine, compare, and transmit an entire set of flags with a single integer operation rather than looping over an array.

Readability tip
Bitmask code reads best when the flag constants have clear names and the mask type is an unsigned integer type wide enough for all the flags you need (`unsigned int` gives you at least 16 flags on every platform, `unsigned long` or a fixed-width type like `uint64_t` for more). Comment each flag's bit position, as in the examples above, so the layout stays clear even without running the code.
  • Define each flag with 1 << n so every flag occupies exactly one distinct bit.

  • Combine flags with |, check one with &, clear one with &= ~flag, toggle one with ^.

  • A bitmask packs many boolean flags into a single integer, using far less memory than an array of booleans.

  • Use an unsigned integer type wide enough to hold every flag you need, and document each bit's meaning.