Skip to content

Bitwise Operations

Bitwise operations work directly on the individual bits of numbers. They're fundamental to low-level programming and are used extensively in systems programming, cryptography, and performance-critical applications.

Basic Bitwise Operations

AND (&)

The AND operation returns 1 only if both bits are 1, otherwise 0.

cpp
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

Example: 5 & 3

cpp
5 = 101 (binary)
3 = 011 (binary)
--------
1 = 001 (binary)

AND is commonly used to:

  • Clear specific bits: value & 0xFF keeps only the lowest 8 bits
  • Check if a bit is set: if (value & 0x01) checks if the lowest bit is 1

OR (|)

The OR operation returns 1 if either bit is 1, otherwise 0.

cpp
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

Example: 5 | 3

cpp
5 = 101 (binary)
3 = 011 (binary)
--------
7 = 111 (binary)

OR is commonly used to:

  • Set specific bits: value | 0x01 sets the lowest bit to 1
  • Combine flags: READ | WRITE combines permission flags

NOT (~)

The NOT operation inverts all bits.

cpp
~0 = 1
~1 = 0

Example: ~5

cpp
5 = 101 (binary)
~5 = 010 (binary) = 2

NOT is commonly used to:

  • Create masks: ~0xFF creates a mask with all bits except the lowest 8
  • Invert conditions: if (!(value & flag)) checks if a flag is NOT set

XOR (^)

The XOR operation returns 1 if exactly one bit is 1, otherwise 0.

cpp
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0

Example: 5 ^ 3

cpp
5 = 101 (binary)
3 = 011 (binary)
--------
6 = 110 (binary)

XOR is commonly used to:

  • Toggle bits: value ^ 0x01 flips the lowest bit
  • Zero a register: x ^ x always equals 0
  • Simple encryption: data ^ key encrypts/decrypts data

Shift Operations

Left Shift (<<)

Shifts all bits left by the specified number of positions, filling with zeros.

cpp
5 << 1 = 10  (101 becomes 1010)
5 << 2 = 20  (101 becomes 10100)

Left shift is equivalent to multiplying by 2^n.

Right Shift (>>)

Shifts all bits right by the specified number of positions.

cpp
5 >> 1 = 2   (101 becomes 10)
5 >> 2 = 1   (101 becomes 1)

Right shift is equivalent to integer division by 2^n.

Practical Examples

Setting and Clearing Bits

cpp
// Set bit at position n
value |= (1 << n);

// Clear bit at position n
value &= ~(1 << n);

// Toggle bit at position n
value ^= (1 << n);

// Check if bit at position n is set
if (value & (1 << n)) {
    // Bit is set
}

Working with Flags

cpp
const int READ = 1;      // 001
const int WRITE = 2;     // 010
const int EXECUTE = 4;   // 100

// Set permissions
int permissions = READ | WRITE;  // 011

// Check if write permission exists
if (permissions & WRITE) {
    // Has write permission
}

// Remove write permission
permissions &= ~WRITE;

Fast Multiplication and Division

cpp
// Multiply by 2^n
int result = value << n;

// Divide by 2^n
int result = value >> n;

// Check if number is power of 2
bool isPowerOf2 = (value & (value - 1)) == 0;

Why This Matters

Bitwise operations are essential for:

  • Memory efficiency: Packing multiple boolean values into a single integer
  • Performance: Faster than arithmetic operations for certain tasks
  • Hardware interaction: Direct manipulation of hardware registers
  • Cryptography: Many encryption algorithms rely heavily on bitwise operations
  • Low-level programming: Assembly instructions often use bitwise operations

Implement addition of two integers using only bitwise operations (no arithmetic operators like +, -, *, /). Use a loop to handle the carry.

cpp
// Implement addition using only bitwise operations
// No arithmetic operators like +, -, *, / are allowed

unsigned int add_without_plus(unsigned int a, unsigned int b) {
    // TODO: Implement addition using only bitwise operations

    return 0; // Replace with your implementation
}