CBit Manipulation Techniques

Bit Manipulation Techniques

Working directly with the individual bits of an integer, using C's bitwise operators (&, |, ^, ~, <<, >>), is a core low-level skill. It shows up constantly in embedded programming, device drivers, networking code, and any performance-critical code that needs to pack information as tightly as possible or manipulate hardware registers directly.

The recipes at a glance

Operation

Expression (bit n, 0-indexed)

Check if bit n is set

(x >> n) & 1

Set bit n

x |= (1 << n)

Clear bit n

x &= ~(1 << n)

Toggle bit n

x ^= (1 << n)

Check if x is a power of two

x > 0 && (x & (x - 1)) == 0

Count set bits

loop shifting and checking the low bit (or __builtin_popcount)

Checking, setting, clearing, toggling a bit

C
#include <stdio.h>

int main(void) {
    unsigned int x = 0b00001010; // 10 in binary

    // Check if bit 1 is set: shift it to the lowest position, mask with 1.
    int bit1 = (x >> 1) & 1;
    printf("bit 1 is %d\n", bit1);

    // Set bit 0: OR with a mask that has only bit 0 set.
    x |= (1 << 0);
    printf("after setting bit 0:   %#x\n", x);

    // Clear bit 3: AND with the complement of a mask that has only bit 3 set.
    x &= ~(1 << 3);
    printf("after clearing bit 3:  %#x\n", x);

    // Toggle bit 2: XOR with a mask that has only bit 2 set.
    x ^= (1 << 2);
    printf("after toggling bit 2:  %#x\n", x);

    return 0;
}
bit 1 is 1
after setting bit 0:   0xb
after clearing bit 3:  0x3
after toggling bit 2:  0x7
Checking for a power of two

A power of two has exactly one bit set (1, 10, 100, 1000, ...). Subtracting 1 from it flips that single set bit to 0 and every bit below it to 1 (e.g. 1000 - 1 = 0111), so a power of two ANDed with itself minus one is always zero — and this is not true for any number that is not a power of two.

C
#include <stdio.h>
#include <stdbool.h>

bool is_power_of_two(unsigned int x) {
    return x > 0 && (x & (x - 1)) == 0;
}

int main(void) {
    unsigned int values[] = {1, 2, 3, 4, 15, 16, 1024};
    for (int i = 0; i < 7; i++) {
        printf("%u: %s\n", values[i], is_power_of_two(values[i]) ? "yes" : "no");
    }
    return 0;
}
1: yes
2: yes
3: no
4: yes
15: no
16: yes
1024: yes
Counting set bits

C
#include <stdio.h>

int count_set_bits(unsigned int x) {
    int count = 0;
    while (x != 0) {
        count += x & 1;   // add 1 if the lowest bit is set
        x >>= 1;          // shift right to examine the next bit
    }
    return count;
}

int main(void) {
    printf("%d\n", count_set_bits(0b10110101)); // 5 bits set
    return 0;
}
5
Compiler builtins can be faster
On GCC and Clang, `__builtin_popcount(x)` computes the same result, often compiling down to a single hardware instruction where the target CPU supports it — worth knowing about once the manual loop above makes sense, especially in performance-sensitive code.

These techniques matter because bitwise operators map almost directly onto what the CPU does in hardware — a handful of instructions with no branching, no memory allocation, and no loops for the single-bit operations. In embedded systems, that efficiency and predictability is often not just nice to have but required, since hardware registers are frequently manipulated one or a few bits at a time.

  • (x >> n) & 1 checks bit n; x |= (1 << n) sets it; x &= ~(1 << n) clears it; x ^= (1 << n) toggles it.

  • x & (x - 1) clears the lowest set bit, which is the trick behind the power-of-two check.

  • Counting set bits by shifting and checking is O(number of bits); compiler builtins like __builtin_popcount are often faster.

  • These operators map closely to real CPU instructions, which is why they are favored in embedded and performance-critical code.