Skip to content

/changelogs/c/c17-to-c23

C17 to C23: what changed (nullptr, constexpr, bool, typeof, #embed)

verified onenvironmentlocal · linux 6.18.44-fc-v233 x64 · GNU bash 5.2.21updated
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

FeatureWhat it doesFirst GCC version
`bool`, `true`, `false`, `alignas`, `alignof`, `static_assert`, `thread_local`Keywords instead of macros from headers13
`nullptr`A null pointer constant with its own type13
`constexpr` objectsObjects with a value fixed at translation time13
`typeof`, `typeof_unqual`Type of an expression; was a GNU extension before13
`auto`Type inference for object definitions13
Empty initializer `{}`Initialise scalars, arrays and VLAs to zero13
`#elifdef`, `#elifndef`Shorter preprocessor conditionals12
Binary literals `0b1010`Integer constants in base 24.3
Digit separators `1'000'000`Readable long constants12
`_BitInt(N)`Bit-precise integer types (x86, x86-64, AArch64 little-endian)14
`#embed`Include a binary file as array data15

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.

bash
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

  1. Find clashes first. Search for your own bool, true, false, nullptr or constexpr names. In C23 they are reserved, so a typedef int bool; is now a compile error.
  2. Pin the standard. Set -std=c17 or -std=c23 in the build. Without a flag the default depends on the compiler version (gnu17 before GCC 15, gnu23 after).
  3. Replace NULL gradually. nullptr has its own type, so it avoids the integer-or-pointer ambiguity of NULL in variadic calls. Both keep working.
  4. 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.
  5. Check the library side. Some C23 additions, such as the %b printf 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.

Sources