Bitwise Operations in C/C++

Why store a bool when 8 of them fit in a byte?

In C, bitwise operators are used to perform operations directly on the binary representations of numbers. These operators work by manipulating individual bits (0s and 1s) in a number.

The following 6 operators are bitwise operators (also known as bit operators as they work at the bit-level). They are used to perform bitwise operations in C.


An example:

int main()
{

    // a = 5 (00000101 in 8-bit binary)
    // b = 9 (00001001 in 8-bit binary)
    unsigned int a = 5, b = 9;

    // The result is 00000001 :
    printf("a & b = %u\n", a & b);

    // The result is 00001101 :
    printf("a|b = %u\n", a | b);

    // The result is 00001100
    printf("a^b = %u\n", a ^ b);

    // The result is 11111111111111111111111111111010 (assuming 32-bit unsigned int)
    printf("~a = %u\n", a = ~a);

    // The result is 00010010
    printf("b << 1 = %u\n", b << 1);

    // The result is 00000100
    printf("b >> 1 = %u\n", b >> 1);
    return 0;
}

Output

a & b = 1
a|b = 13
a^b = 12
~a = 4294967290
b<<1 = 18
b>>1 = 4

Some Noteworthy Facts

Bitmasks

A bitmask is a binary pattern used to select, set, clear, or toggle specific bits in a variable — usually with the help of bitwise operators.

Here's a refresher in C/C++ style syntax:

#define BIT0 (1 << 0)  // 00000001
#define BIT1 (1 << 1)  // 00000010
#define BIT2 (1 << 2)  // 00000100
...

If you want to store multiple binary flags in one byte, you can use each bit as a switch:

uint8_t flags = 0;
flags |= BIT2;  // turn on bit 2
flags &= ~BIT1; // turn off bit 1
if (flags & BIT2) {
    // bit 2 is on
}

Bitmasks in Embedded Engineers

(From https://medium.com/@nikheelvs/how-embedded-engineers-use-bitmasks-and-why-you-should-too-2befe2490889)

Whether you're toggling an LED or decoding a TCP header, bitmasks are a secret weapon that give you both power and performance. In the world of embedded systems, every byte counts — but the beauty of bit-level thinking goes far beyond microcontrollers.

Some Real Use Cases in Embedded Systems:

GPIO State Control

In firmware for microcontrollers (like STM32, ESP32, etc.), you'll often manipulate GPIO ports directly:

GPIO_PORT |= (1 << 5);   // Set pin 5 high
GPIO_PORT &= ~(1 << 5);  // Set pin 5 low

Why? Because hardware registers expose bit fields — one bit per pin. You can't waste time or RAM with structs or variables.

Flags in Event Loops

Instead of polling multiple boolean variables, embedded loops often use a single byte (or uint32_t, or...) for flag storage:

#define EVENT_BUTTON_PRESS (1 << 0)
#define EVENT_TIMEOUT      (1 << 1)
#define EVENT_ERROR        (1 << 2)

if (event_flags & EVENT_BUTTON_PRESS) {
    handle_button();
    event_flags &= ~EVENT_BUTTON_PRESS;
}

It’s fast, memory-efficient, and avoids branching where unnecessary.