C23 is the informal name for ISO/IEC 9899:2024, the next standard for the C programming language, which will replace C17 (standard ISO/IEC 9899:2018).[1] It was started in 2016 informally as C2x,[2] and was expected to be published in 2024.[3] The most recent publicly available working draft of C23 was released on April 1, 2023.[4] The first WG14 meeting for the C2x draft was held in October 2019,[5] virtual remote meetings were held in 2020 due to the COVID-19 pandemic, then various teleconference meetings continued to occur through 2024.
Add memset_explicit() function in <string.h> to erase sensitive data, where memory store must always be performed regardless of optimizations.[6]
Add memccpy() function in <string.h> to efficiently concatenate strings – similar to POSIX and SVID C extensions.[7]
Add strdup() and strndup() functions in <string.h> to allocate a copy of a string – similar to POSIX and SVID C extensions.[8]
Add memalignment() function in <stdlib.h> to determine the byte alignment of a pointer.[9]
Add bit utility functions / macros / types in new header <stdbit.h> to examine many integer types. All start with stdc_ to minimize conflict with legacy code and 3rd party libraries.[10]
In the following, replace * with uc, us, ui, ul, ull for five function names, or blank for a type-generic macro.[10]
Add stdc_count_ones*() and stdc_count_zeros*() to count number of 1 or 0 bits in value.[10]
Add stdc_leading_ones*() and stdc_leading_zeros*() to count leading 1 or 0 bits in value.[10]
Add stdc_trailing_ones*() and stdc_trailing_zeros*() to count trailing 1 or 0 bits in value.[10]
Add stdc_first_leading_one*() and stdc_first_leading_zero*() to find first leading bit with 1 or 0 in value.[10]
Add stdc_first_trailing_one*() and stdc_first_trailing_zero*() to find first trailing bit with 1 or 0 in value.[10]
Add stdc_has_single_bit*() to determine if value is an exact power of 2 (return true if and only if there is a single 1 bit).[10]
Add stdc_bit_floor*() to determine the largest integral power of 2 that is not greater than value.[10]
Add stdc_bit_ceil*() to determine the smallest integral power of 2 that is not less than value.[10]
Add stdc_bit_width*() to determine number of bits to represent a value.[10]
Add timegm() function in <time.h> to convert time structure into calendar time value - similar to function in glibc and musl libraries.[11]
New <math.h> functions based on IEEE 754-2019 recommendations, such as trigonometry functions operating on units of and exp10.[12]
Add #elifdef and #elifndefdirectives,[15] which are essentially equivalent to #elif defined and #elif !defined. Both directives were added to C++23 standard and GCC 12.[16]
Add #embed directive for binary resource inclusion and __has_embed allowing the availability of a resource to be checked by preprocessor directives.[17]
Add __has_include allowing the availability of a header to be checked by preprocessor directives.[19]
Add __has_c_attribute allowing the availability of an attribute to be checked by preprocessor directives.[20] (see "C++ compatibility" group for new attribute feature)
Add __VA_OPT__ functional macro for variadic macros which expands to its argument only if a variadic argument has been passed to the containing macro.[21]
The meaning of the auto keyword was changed to cause type inference while also retaining its old meaning of a storage class specifier if used alongside a type. Unlike C++, C23 allows type inference only for object definitions (no inferring function return type or function parameter type).[29]
Compatibility rules for structure, union, and enumerated types were changed to allow a redeclaration of a compatible type with the same tag.[30]
Exact-width integer may now exceed intmax_t (N2888).[31]
Add wb and uwb integer literal suffixes for _BitInt(N) and unsigned_BitInt(N) types,[32] such as 6uwb yields an unsigned _BitInt(3), and -6wb yields a signed _BitInt(4) which has three value bits and one sign bit.
Add ' digit separator to literal constants,[34] such as 0xFE'DC'BA'98 (equating to 0xFEDCBA98), 299'792'458 (equating to 299792458), 1.414'213'562 (equating to 1.414213562).
Add the ability to specify the underlying type of an enum.[35]
Allow enums with no fixed underlying type to store values that are not representable by int.[36]
Zero initialization with {} (including initialization of VLAs).[41]
Variadic functions no longer need a named argument before the ellipsis and the va_start macro no longer needs a second argument nor does it evaluate any argument after the first one if present.[42]
Add C++11 style attribute syntax[43] using double square brackets [[]]. In addition to C++11 attributes listed below, add new attributes:
[[unsequenced]][44] allows compiler optimizations for functions producing repeatable outputs only based on their parameters
[[reproducible]],[44] similar to [[unsequenced]], but for functions whose call order also matters
Various syntax changes improve compatibility with C++, such as labels before declarations, unnamed function arguments, zero initialization with {}, variadic functions without named argument, C++11 style attributes, _Static_assert (see Syntax). For labels at the end of compound statements a corresponding change was made to C++23.[46]
Add C++-style attributes (see Syntax). Add attributes [47][[deprecated]],[48][[fallthrough]],[49][[maybe_unused]],[50][[nodiscard]],[51] and [[noreturn]] attribute for compatibility with C++11, then deprecate _Noreturn, noreturn, header <stdnoreturn.h> features introduced in C11.[52] Duplicate attributes are allowed for compatibility with C++23.[53] All standard attributes can also be surrounded by double underscores (e.g. [[__deprecated__]] is equivalent to [[deprecated]]).
Support for the ISO/IEC 60559:2020, the current version of the IEEE 754 standard for floating-point arithmetic, with extended binary floating-point arithmetic and (optional) decimal floating-point arithmetic.[56][57]
Add char8_t type for storing UTF-8 encoded data and change the type of u8 character constants and string literals to char8_t. Also, the functions mbrtoc8() and c8rtomb() to convert a narrow multibyte character to UTF-8 encoding and a single code point from UTF-8 to a narrow multibyte character representation respectively.[59]
Clarify that all char16_t strings and literals shall be UTF-16 encoded, and all char32_t strings and literals shall be UTF-32 encoded, unless otherwise explicitly specified.[60]