static_assert (Compile-Time Assertion)

cardimg

In C, we often use #error preprocessor directives or runtime checks like assert() to catch bugs.

  • assert(x > 0) runs on the device. If it fails, your firmware crashes or halts while the user is using it.
  • static_assert runs on the compiler. If it fails, your code refuses to compile.

This is the ultimate safety net: catching fatal configuration errors before the firmware is even generated.

Syntax & Usage

1. Basic Usage

It takes a boolean constant expression and an optional error message.

// Syntax: static_assert(condition, "Error Message");

// Ensure this code is compiled for a 32-bit system
static_assert(sizeof(void*) == 4, "Error: Code requires 32-bit architecture");

// Ensure integer is large enough
static_assert(sizeof(int) >= 4, "Error: int must be at least 4 bytes");

2. Validating Struct Sizes (Padding Check)

Crucial for memory-mapped structs or communication packets.

struct Packet {
    uint8_t id;
    uint32_t payload;
};

// Check if compiler added padding bytes
static_assert(sizeof(Packet) == 5, "Error: Packet struct has padding! Use #pragma pack.");

Comparison: Runtime vs Compile-Time

Featureassert() (C/C++)static_assert (C++)
When it runsRuntime (on the CPU).Compile-Time (on PC).
CostCPU Cycles + Flash code size.Zero overhead (0 bytes).
FailureFirmware crash / infinite loop.Compilation Error.
ConditionAny variable/state.Must be constexpr (known at compile time).

Relevance in Embedded/Firmware

1. Protocol Packet Safety

When defining structs for UART/SPI/CAN frames, compiler padding can silently break communication.

static_assert(sizeof(Frame) == 8, ...) ensures that if someone adds a field or changes a type, the build breaks immediately, preventing hard-to-debug communication failures.

2. Buffer Configuration Checks

If you have a circular buffer that requires a power-of-two size for efficient bitwise wrapping:

constexpr int BUF_SIZE = 100; // Oops, not power of 2
static_assert((BUF_SIZE & (BUF_SIZE - 1)) == 0, "Buffer size must be power of 2");

3. Validating Type Aliases

If you switch platforms (e.g., STM32 to AVR), types like int might change size.

static_assert ensures your assumptions (e.g., "I need a 64-bit timestamp") hold true on the new hardware.

Common Pitfalls (Practical Tips)

PitfallDetails
❌ Runtime Variables

You cannot check variables that change at runtime.

int x = read_gpio(); static_assert(x > 0, ...); is invalid. Use standard assert for this.

❌ Meaningless MessagesDon't just say "Error". Be descriptive: "PLL Config Error: System clock too high for selected voltage range." This helps other developers fix the config file instantly.
✅ Library ValidationIf you write a template library (e.g., a generic Ring Buffer), use static_assert to prevent users from instantiating it with invalid types (e.g., a buffer of void).

 

 

 

Concept understood? Let's apply and learn for real

Practice now