/changelogs/c/c17-to-c23
C17 to C23: what changed (nullptr, constexpr, bool, typeof, #embed)
- tool
- C
- versions
- C17 → C23
C23, the 2023 revision of ISO C (published in 2024), adds nullptr, constexpr objects, bool/true/false as keywords, typeof, auto type inference, #embed, binary literals and digit separators. C17 itself only corrected and clarified C11, so the real migration is C17 to C23. Most new features need GCC 13 or later, and C23 became the default dialect in GCC 15.
Language changes
| Feature | What it does | First GCC version |
|---|---|---|
| `bool`, `true`, `false`, `alignas`, `alignof`, `static_assert`, `thread_local` | Keywords instead of macros from headers | 13 |
| `nullptr` | A null pointer constant with its own type | 13 |
| `constexpr` objects | Objects with a value fixed at translation time | 13 |
| `typeof`, `typeof_unqual` | Type of an expression; was a GNU extension before | 13 |
| `auto` | Type inference for object definitions | 13 |
| Empty initializer `{}` | Initialise scalars, arrays and VLAs to zero | 13 |
| `#elifdef`, `#elifndef` | Shorter preprocessor conditionals | 12 |
| Binary literals `0b1010` | Integer constants in base 2 | 4.3 |
| Digit separators `1'000'000` | Readable long constants | 12 |
| `_BitInt(N)` | Bit-precise integer types (x86, x86-64, AArch64 little-endian) | 14 |
| `#embed` | Include a binary file as array data | 15 |
The versions come from the GCC C23 status table. __VA_OPT__ (GCC 8) and __has_include (GCC 5) were also standardised, but compilers had them long before C23.
See the difference
The block below compiles one file that uses constexpr, nullptr, bool without stdbool.h and a binary literal. It fails as C17 and builds as C23. GCC 13 spells the C23 mode -std=c2x; GCC 14 and later accept -std=c23.
mkdir -p /tmp/work && cd /tmp/work
cat > demo.c <<'EOF'
int main(void) {
constexpr int n = 4;
int *p = nullptr;
bool ok = true;
int x = 0b1010;
return (p == nullptr && ok && n == 4 && x == 10) ? 0 : 1;
}
EOF
gcc -std=c17 -c demo.c 2>&1 | grep -m1 "undeclared"
gcc -std=c2x -c demo.c && echo "c2x: ok"Output
demo.c:2:5: error: ‘constexpr’ undeclared (first use in this function) c2x: ok
Migration checklist
- Find clashes first. Search for your own
bool,true,false,nullptrorconstexprnames. In C23 they are reserved, so atypedef int bool;is now a compile error. - Pin the standard. Set
-std=c17or-std=c23in the build. Without a flag the default depends on the compiler version (gnu17 before GCC 15, gnu23 after). - Replace
NULLgradually.nullptrhas its own type, so it avoids the integer-or-pointer ambiguity ofNULLin variadic calls. Both keep working. - Turn on warnings. Build with
-Wall -Wextra(see gcc -Wall -Wextra) so the new diagnostics are visible, and run the sanitizer described in undefined behavior. - Check the library side. Some C23 additions, such as the
%bprintf conversion, also depend on the C library version, not only on the compiler.
A name that was not declared at all gives the error in use of undeclared identifier; under -std=c17 that is what constexpr produces in the example above.
FAQ
Is C23 the default in my compiler?
Only in recent GCC. The GCC C status page says C23 mode is the default since GCC 15, and the C dialect options page lists gnu23 as the default for C code. Older GCC releases default to gnu17, so pass -std=c23 (or -std=c2x on GCC 13) to opt in explicitly.
What did C17 change compared with C11?
Almost nothing for programmers. GCC's status page says C17 brings no major changes, only technical corrections and clarifications to C11. That is why moving from C11 to C17 needs no source changes, while the step to C23 adds keywords and library features.
Do I have to remove my own bool typedef to build as C23?
Yes, if it redefines bool, true or false. In C23 these are keywords, so a typedef or macro with the same name is an error. Delete your definition and include nothing extra: the keywords are built in, and stdbool.h remains available for older standards.