Question bank — Compile-time assertions — static_assert
Before you start, remember the one sentence that resolves most of these: a static_assert is evaluated by the compiler, so its condition must be a constant expression — a value fully known without running the program.
True or false — justify
C11 lets you omit the message string in static_assert.
A passing static_assert adds a tiny runtime check that the CPU skips quickly.
static_assert(1 == 1); and assert(1 == 1); are basically the same thing.
static_assert fires at compile time and needs a constant; assert (from <assert.h>) fires at run time and can inspect variables. They live in different phases of the program's life.You can write static_assert in C11 without including any header.
static_assert is a macro in <assert.h>. The raw keyword _Static_assert needs no header at all.#error can check whether sizeof(int) == 4.
#error runs in the preprocessor, which has no type information — it cannot evaluate sizeof. Only the compiler (via static_assert) knows type sizes.static_assert(sizeof(int) == 4); will compile fine as C23.
static_assert is a real keyword and the message is optional, so a lone condition is legal. Under C11 the same line fails for lack of a message.Compiling out assert with NDEBUG also disables static_assert.
NDEBUG only silences the runtime assert. static_assert is unaffected — it is not a debugging aid you can turn off, it is a build gate.A false static_assert inside a function you never call is harmless.
Spot the error
int n = read_config();
static_assert(n > 0, "n must be positive");::: n is a runtime variable, so n > 0 is not a constant expression — this fails to compile. For runtime data use assert instead; static_assert is only for compile-time-known values.
// C11 source, no includes
static_assert(sizeof(long) >= 4, "long too small");::: In C11 the spelling static_assert is a macro — without #include <assert.h> the name is undefined. Fix: include the header, or write the raw keyword _Static_assert.
#define SIZE 100
#error (SIZE % 2 == 0) ? 0 : "SIZE must be even"::: #error does not evaluate expressions — everything after it is just text printed unconditionally. To conditionally check an even size you need #if SIZE % 2 != 0 … #error …, or a static_assert in code.
static_assert(strlen("hi") == 2, "wrong");::: strlen is a runtime function call, so the argument is not a constant expression — it won't compile. Use sizeof("hi") - 1 (a compile-time constant, minus the null terminator) if you truly need it at build time.
static_assert(get_flag() ? 1 : 0, "flag off");::: A function call get_flag() can never be a constant expression in C, so this is illegal. Constant conditions must be built from literals, sizeof, enum values, and #defined constants only.
enum { A = 1, B = 2 };
static_assert(A + B, "sum is zero"); // meant to catch A+B == 0::: The condition is just the value 3, which is non-zero (true), so it silently passes and checks nothing meaningful. The author forgot the comparison; they wanted static_assert(A + B != 0, ...).
Why questions
Why must the condition be a constant, not just "any true expression"?
Why does static_assert cost zero runtime while assert costs a little?
static_assert is fully resolved at compile time and produces no code; assert compiles into an actual runtime if-check-and-abort that executes each time the line runs (unless removed by NDEBUG).Why prefer static_assert(sizeof(int)==4) over a runtime check for the same thing?
int is fixed the instant you compile — it never varies per run or per input. A runtime check would waste cycles re-verifying a truth already known, and could ship in a broken binary; the compile-time check makes the broken build impossible to produce.Why can static_assert use sizeof but #error cannot?
sizeof needs the compiler's knowledge of types; #error acts in the preprocessor, an earlier phase that only manipulates text tokens and knows nothing about types or sizes.Why is static_assert(sizeof(names)/sizeof(names[0]) == COUNT) a constant expression?
COUNT without running anything.Why does putting a static_assert at file scope (outside any function) work?
static_assert is a declaration, so it is legal anywhere a declaration is — at file scope, inside a struct, or inside a function body. It needs no surrounding statement or executable context.Edge cases
static_assert(0, "always here"); — what happens?
static_assert(-1, "check"); — passes or fails?
0 triggers the diagnostic.static_assert(0.0 == 0.0, "float check"); in C11 — legal?
int (1) here so it may pass, but relying on floating-point constants is fragile and non-portable — keep conditions integer-valued.Can two static_asserts at the same scope both be false, and which message shows?
A static_assert inside a struct with a false condition — does it still fire?
static_assert may appear among struct members and is checked when the type is compiled — the build fails even though no object of that struct exists yet.static_assert(sizeof(char) == 1); — is this ever false?
sizeof(char) is 1 by definition in C, on every platform. So this particular assertion can never fail; it is a tautology, useful only as documentation of intent, not as a real guard.