ccompiler.inOnline C Compiler & Docs
Engineering Blog2026-08-147 min read

Master bitwise operators in C (&, |, ^, ~, <<, >>). Learn bit masking, setting, clearing, toggling bits, and high-performance register tricks.

In C programming, Bitwise Operators allow developers to manipulate individual binary bits (0s and 1s) directly inside CPU registers.

Because CPUs execute bitwise operations in a single clock cycle, bit manipulation is the foundation of high-performance computing, device drivers, embedded microcontrollers, cryptography, network protocols, and game engine optimizations.

In this comprehensive guide, you will master all 6 bitwise operators in C, learn the fundamental "Big 4" Bit Masking techniques (Set, Clear, Toggle, Check), discover famous algorithmic bit hacks (like Brian Kernighan's population count and power-of-two tests), and explore runnable C code examples.


1. The 6 Bitwise Operators in C: Truth Tables

Standard C provides 6 bitwise operators that operate on integer types (char, short, int, long, signed and unsigned):

OperatorNameSyntaxDescriptionExample (A=5 (0101_2), B=3 (0011_2))
&Bitwise ANDA & BResult bit is 1 only if both operand bits are 15 & 3 $→$ 0001 (1)
|Bitwise ORA | BResult bit is 1 if either operand bit is 15 | 3 $→$ 0111 (7)
^Bitwise XORA ^ BResult bit is 1 if bits are different5 ^ 3 $→$ 0110 (6)
~Bitwise NOT~AInverts all bits (0 becomes 1, 1 becomes 0)~5 $→$ ...11111010 (-6)
<<Left ShiftA << nShifts bits left by n positions (multiplies by $2^n$)5 << 1 $→$ 1010 (10)
>>Right ShiftA >> nShifts bits right by n positions (divides by $2^n$)5 >> 1 $→$ 0010 (2)

2. Visualizing Truth Tables

text (ISO Standard)
 Bit A | Bit B | A & B (AND) | A | B (OR) | A ^ B (XOR) | ~A (NOT)
-------+-------+-------------+------------+-------------+----------
   0   |   0   |      0      |     0      |      0      |    1
   0   |   1   |      0      |     1      |      1      |    1
   1   |   0   |      0      |     1      |      1      |    0
   1   |   1   |      1      |     1      |      0      |    0

3. The "Big 4" Bit Masking Recipes

Bit masking is the technique of using a specific pattern of bits (a mask) along with bitwise operators to modify or inspect specific bit positions without altering surrounding data.


Recipe 1: Setting the n-th Bit (Force to 1)

To force bit n to 1, create a mask with (1 << n) and apply Bitwise OR (|):

c (ISO Standard)
// Set bit at index n (0-indexed)
number |= (1 << n);
text (ISO Standard)
   Number:   0010 0100 (36)
   Mask:     0000 0010 (1 << 1)
   -----------------------------
OR Result:   0010 0110 (38)  <-- Bit 1 is now 1

Recipe 2: Clearing the n-th Bit (Force to 0)

To force bit n to 0, invert the mask with ~(1 << n) and apply Bitwise AND (&):

c (ISO Standard)
// Clear bit at index n
number &= ~(1 << n);
text (ISO Standard)
   Number:    0010 0110 (38)
   Inverted:  1111 1101 (~(1 << 1))
   -----------------------------
AND Result:   0010 0100 (36)  <-- Bit 1 is now 0

Recipe 3: Toggling the n-th Bit (Flip 0 <-> 1)

To flip the state of bit n, apply Bitwise XOR (^) with (1 << n):

c (ISO Standard)
// Toggle bit at index n
number ^= (1 << n);

Recipe 4: Checking / Reading the n-th Bit

To inspect if bit n is 1 or 0:

c (ISO Standard)
// Returns 1 if set, 0 if cleared
int isSet = (number >> n) & 1;
// Alternatively:
int isSetBool = (number & (1 << n)) != 0;

4. 5 High-Performance Bitwise Algorithms & Hacks


Hack 1: Check if an Integer is a Power of Two

A power of two in binary has exactly one bit set (e.g., $8 = 1000_2$). Subtracting 1 flips all lower bits ($7 = 0111_2$). Applying n & (n - 1) clears the single set bit to 0:

c (ISO Standard)
#include <stdbool.h>

bool isPowerOfTwo(unsigned int n) {
    return (n > 0) && ((n & (n - 1)) == 0);
}

Hack 2: Swap Two Variables Without a Temporary Variable

Using the self-inverting property of XOR (x ⊕ x = 0 and x ⊕ 0 = x):

c (ISO Standard)
void xorSwap(int *a, int *b) {
    if (a != b) { // Guard against same memory address
        *a ^= *b;
        *b ^= *a;
        *a ^= *b;
    }
}

Hack 3: Check Even vs. Odd Fast

The least significant bit (LSB, bit 0) of every odd number is 1. Checking n & 1 avoids CPU division/modulo instructions:

c (ISO Standard)
bool isOdd(int n) {
    return (n & 1); // 1 = Odd, 0 = Even
}

Hack 4: Count Set Bits (Brian Kernighan’s Algorithm)

Brian Kernighan’s algorithm runs in $O(set bits)$ time by clearing the lowest set bit on every iteration:

c (ISO Standard)
int countSetBits(unsigned int n) {
    int count = 0;
    while (n > 0) {
        n &= (n - 1); // Clears the lowest set bit
        count++;
    }
    return count;
}

(In GCC, you can also use the hardware-accelerated intrinsic __builtin_popcount(n)).


Hack 5: High-Speed Multiplication & Division by Powers of Two

  • x << 3 is equivalent to $x × 8$ ($x × 2^3$).
  • x >> 2 is equivalent to $x / 4$ ($x / 2^2$).

5. Complete Runnable C Program

c (ISO Standard)
#include <stdio.h>
#include <stdbool.h>

void printBinary(unsigned char num) {
    for (int i = 7; i >= 0; i--) {
        printf("%d", (num >> i) & 1);
    }
    printf(" (Decimal: %d)\n", num);
}

int main(void) {
    unsigned char reg = 0b00100100; // 36

    printf("Initial value:       ");
    printBinary(reg);

    // 1. Set bit 1
    reg |= (1 << 1);
    printf("After setting bit 1: ");
    printBinary(reg); // 00100110 (38)

    // 2. Toggle bit 5
    reg ^= (1 << 5);
    printf("After toggling bit 5:");
    printBinary(reg); // 00000110 (6)

    // 3. Clear bit 2
    reg &= ~(1 << 2);
    printf("After clearing bit 2:");
    printBinary(reg); // 00000010 (2)

    // 4. Test bit status
    printf("\nIs bit 1 set? %s\n", ((reg >> 1) & 1) ? "YES" : "NO");
    printf("Is bit 0 set? %s\n", ((reg >> 0) & 1) ? "YES" : "NO");

    return 0;
}

Frequently Asked Questions (FAQ)

1. What is the difference between Logical (&&, ||) and Bitwise (&, |) operators?

  • Logical Operators (&&, ||): Evaluate entire boolean expressions (true or false) and feature short-circuit evaluation (e.g., if the left side of && is false, the right side is never evaluated).
  • Bitwise Operators (&, |): Operate on every individual bit in parallel and never short-circuit.

2. What is the difference between Arithmetic and Logical Right Shift?

  • Logical Right Shift (>> on unsigned int): Shifts bits right and always fills vacated high-order bits with 0.
  • Arithmetic Right Shift (>> on signed int): Shifts bits right and replicates the sign bit (1 for negative numbers, 0 for positive numbers) to preserve algebraic sign.

3. Can bit shifting cause Undefined Behavior in C?

Yes. Shifting by a negative count (e.g., x << -1) or by an amount greater than or equal to the bit width of the integer (e.g., 1 << 32 on a 32-bit int) triggers ISO C undefined behavior.


Conclusion

Bitwise operators provide direct, low-level control over binary data. By mastering the core masking operations (|, &, ^, ~) and utilizing shift arithmetic, you can write concise, lightning-fast C code for embedded systems, algorithms, and system software.


Related Articles & References