constexpr in C23
/ KON-stek-spr /
In C, a const variable means 'you may not modify it', but it is not necessarily a compile-time constant — for instance you still could not (portably) use a const int as an array size or a case label. C23 adds constexpr, which declares an OBJECT whose value is a true constant expression known at compile time, so it can be used everywhere the language demands a constant.
You write constexpr int N = 16; and now N is a genuine compile-time constant: it can size an array, label a case, or feed a static_assert, and the compiler guarantees it has no runtime initialization. The initializer must itself be a constant expression, and the type is limited to suitable kinds (integer, floating, and similar; not, in C23, general user functions — C's constexpr is much narrower than C++'s, applying to objects, not to functions). Think of it as a named, typed replacement for the old #define-a-magic-number habit, but one that respects scope and type and participates in real type checking.
It matters because it replaces error-prone preprocessor constants with proper typed names: constexpr double PI = 3.14159 has a type, obeys scope, and shows up in the debugger, unlike a #define. The honest caveat to keep straight: in C23 constexpr applies to OBJECTS, not to functions — there is no constexpr function in C23 the way there is in C++, so do not expect to mark a function constexpr and have it run at compile time.
constexpr int N = 16; int buf[N]; // ok: N is a real compile-time constant static_assert(N % 8 == 0, "N must be a multiple of 8"); constexpr double PI = 3.14159; // typed, scoped — unlike #define PI ...
constexpr names a typed compile-time constant usable as an array size, case label, or static_assert operand.
C23 constexpr applies to OBJECTS, not functions: it is far narrower than C++'s constexpr, so there is no compile-time-evaluated constexpr function in C.