Bitwise and Logical Operators in Embedded C: A Practical Guide

In embedded systems programming, understanding low-level operations like bitwise and logical operators is essential for efficient memory usage and hardware control. Below is a practical explanation of common operators such as |, &, <<, >>, &&, ||, ++i, and i++, along with illustrative code examples.

Data Types and Binary Representation

Key data types in C (on most 32-bit embdeded platforms):

  • char: 1 byte (8 bits)
  • int: 4 bytes (32 bits), signed by default

A 32-bit signed integer ranges from -2,147,483,648 to 2,147,483,647. Values beyond this wrap around due to two’s complemant representation.

Bitwise OR (|)

The OR operator sets a bit to 1 if either operand has a 1 in that position.

uint32_t val = 48;        // 0x00000030 → binary: 0011 0000
uint32_t result = val | 0xFF;  // 0x000000FF → result = 0x000000FF (255)

Commonly used to set specific bits without affecting others.

Bitwise AND (&)

The AND operator yields 1 only if both operands have 1 in that bit position.

uint32_t val = 48;        // 0x30
uint32_t masked = val & 0xFF;  // Keeps lower 8 bits → 0x30 (48)

Frequently used to extract or mask out portions of a value (e.g., isolating a byte).

Left and Right Shifts (<<, >>)

Shift operators move bits left or right:

  • x << n: shifts bits left by n positions (equivalent to multiplying by 2ⁿ)
  • x >> n: shifts bits right by n positions (equivalent to dividing by 2ⁿ for unsigned values)
uint8_t byte = 48;       // 0b00110000
uint8_t shifted = byte << 2;  // 0b11000000 → 192

Used in packing/unpacking multi-byte data (e.g., combining two bytes into a 16-bit value):

uint8_t high = 48, low = 78;
uint16_t combined = (high << 8) | low;  // 0x304E

Logical Operators (&&, ||)

These evaluate boolean truthiness (non-zero = true):

  • a && b: true only if both a and b are non-zero
  • a || b: true if either a or b is non-zero

Short-circuit evaluation appleis: in a && b, if a is false, b is not evaluated.

Increment Operators: ++i vs i++

  • ++i (pre-increment): increments i, then returns the new value
  • i++ (post-increment): returns the current value of i, then increments it
int i = 1;
if (i++ == 1) { /* true — uses original value */ }
// now i = 2

if (++i == 3) { /* true — increments first to 3 */ }

Practical Example

#include <stdio.h>
#include <stdint.h>

int main() {
    uint32_t d1 = 48, d2 = 78;
    uint32_t packed = ((d1 & 0xFF) << 8) | (d2 & 0xFF);  // 0x304E
    uint32_t shifted = (d1 & 0xFF) >> 4;                 // 0x03

    printf("Packed: 0x%04X\n", packed);   // Output: 0x304E
    printf("Shifted: 0x%X\n", shifted);   // Output: 0x3

    int x = 1;
    if (x++ == 1 && ++x == 3) {
        printf("Condition met\n");  // Executes
    }

    return 0;
}

Tags: C Embedded Systems bitwise operators logical operators shift operators

Posted on Sun, 04 Oct 2026 16:24:57 +0000 by d_mc_a