Modern C (C11/C17/C23)

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.

Also called
constexpr objectnamed compile-time constant編譯期常數物件