- References
- Function Overloading
- Default Function Arguments
- Inline Function
- Dynamic Memory Allocation
- Placement New
- nullptr
- Namespaces
- Type Aliases
- Enum classes
- constexpr
- static_assert
- mutable Keyword
- auto Keyword
- Smart Pointers
- Basics of Classes
- Constructors
- Destructors
- Operator Overloading
- Copy Semantics
- Move Semantics
- Composition, RAII & Ownership
- Inheritance
- Polymorphism
- Abstraction
- Encapsulation
- Template
- Static Memory
- Friend Function
- this Pointer
- Function Pointer
- Lambdas and Callback Management
- Union
static_assert (Compile-Time Assertion)

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_assertruns 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
| Feature | assert() (C/C++) | static_assert (C++) |
|---|---|---|
| When it runs | Runtime (on the CPU). | Compile-Time (on PC). |
| Cost | CPU Cycles + Flash code size. | Zero overhead (0 bytes). |
| Failure | Firmware crash / infinite loop. | Compilation Error. |
| Condition | Any 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)
| Pitfall | Details |
|---|---|
| ❌ Runtime Variables | You cannot check variables that change at runtime.
|
| ❌ Meaningless Messages | Don'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 Validation | If 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