Bitwise Operations

In C, bitwise operations allow direct manipulation of individual bits within a byte, word, or register. These operations are performed using the following operators:

  • | → Bitwise OR — typically used to set a bit
  • & → Bitwise AND — used to clear or check a bit
  • ^ → Bitwise XOR — used to toggle (invert) a bit
  • ~ → Bitwise NOT — used to flip all bits (1 to 0, 0 to 1)
  • << >> → Bit shift left/right — used to move bit positions
     

Common bit-masking patterns:

reg |= (1 << n);     // Set bit n
reg &= ~(1 << n);    // Clear bit n
reg ^= (1 << n);     // Toggle bit n
if (reg & (1 << n))  // Check if bit n is set

These operations are used to target and modify only specific bits, without disturbing others.

8-bit Visualization Example

Bit76543210
Value1286432168421

E.g.

  • To set bit 3 → reg |= (1 << 3)
  • To clear bit 6 → reg &= ~(1 << 6)
  • To check bit 0 → reg & (1 << 0)
  • To toggle but 3 → reg ^= (1 << 3)

32-bit Register Usage

Bitwise techniques apply the same way for uint32_t types — often used in 32-bit MCUs for status/configuration registers.

Example:

ctrl_reg |= (1U << 23);  // Set bit 23 in a 32-bit control register

 

Common Pitfalls (Practical Tips)

  • Forgetting parentheses: 1 << n must be inside parentheses during masking:
     ✅ reg |= (1 << 4) vs ❌ reg |= 1 << 4 & 0xF
  • Using signed types: Never use int for register work — use uint8_t, uint16_t, or uint32_t.
     Signed values may cause undefined behavior when shifting, as MSB (Most Significant Bit) used for sign.
  • Wrong shift width: Shifting more than the data type width (e.g. 1 << 32 on a 32-bit int) is undefined.
  • Accidental overwrite:
reg = (1 << 2); // WRONG: overwrites entire register  
reg |= (1 << 2); // RIGHT: sets only the 2nd bit
  • Check before toggle: Be careful when toggling flags — you may unintentionally clear a set flag.
     

Relevance in Embedded/Firmware

  • All MCU peripherals are controlled via register bits — timers, GPIOs, UART, ADC, interrupts, etc.
  • Bit masking ensures safe modification without overwriting unrelated fields.
  • Used in flags, control masks, interrupt status checks, and power/clock configuration.

Concept understood? Let's apply and learn for real

Practice now