Appendix G — What C23 added, and where this book covers it
Every edition of the standard records “what changed” about itself (C23′s annex M.2). Taking that list as the frame, this appendix gathers where in this book each item is covered. It is a place for someone who already knows the new standard to ask “which chapter tells that story”, and equally for someone who has finished the book to check “did I meet all of C23”.
★ This book does not teach C23 separately. Rather than teaching the old way first and appending the new, it explains in C23 from the start and adds “it used to be like this” only where that helps. So the items below do not sit together; they are scattered through their own subjects. This table stitches those places back together.
The language#
| What | In brief | Where |
|---|---|---|
bool, true, false and other promotions | what were macros became words | chapter 87 |
nullptr and nullptr_t | a null constant with a type of its own | chapters 37 and 87 |
constexpr | an object whose value is fixed at translation time | chapters 21 and 87 |
typeof, typeof_unqual | write down an expression’s type verbatim | chapter 87 |
auto type inference | the type is drawn from the initialiser | chapter 87 |
attributes [[…]] | write intent no type can hold (seven of them) | chapter 87 |
_BitInt(N) | an integer whose width you choose | chapters 21 and 28 |
| two’s complement settled, old sign forms removed | integer representation pinned to one | chapters 6 and 28 |
| limits redefined in terms of width | the negative end of the guaranteed range moved | chapter 28 |
binary literals 0b | write bits as bits | chapters 21 and 51 |
digit separator ' | 1'000'000 reads in groups | chapter 21 |
empty initialiser {} | initialisation that zeroes the padding too | chapter 47 |
| storage class on compound literals | their lifetime can be changed | chapter 48 |
| fixed underlying type for enums | enum E : unsigned { … } | chapter 27 |
| relaxed tag compatibility | compatible within one translation unit too | chapter 47 |
| labels in more places | before declarations and at a block’s end | chapter 32 |
| K&R identifier-list definitions removed | the old definition syntax is gone | chapter 62 |
f() = f(void) | empty parentheses now mean no parameters | chapter 62 |
| parameter names may be omitted | even in a definition | chapter 62 |
va_start needs no second argument | ... may stand with no parameter before it | chapter 63 |
| variably modified types mandated | VLAs themselves stay optional | chapter 40 |
| Unicode identifiers | which characters may appear in a name is settled | chapter 8 |
@, $ and the grave accent (U+0060) added to the character set | more characters may appear in source | chapter 8 |
u8 character constants | the string prefix now works on characters | chapter 21 |
u8, u, U encodings pinned | settled as UTF-8, UTF-16, UTF-32 | chapters 8 and 75 |
| literal encodings separated | split apart from the execution character set | chapter 8 |
| wide/narrow literal concatenation removed | mixing them is gone | chapter 43 |
| potentially reserved identifiers | a mark between reserved and not | chapter 59 |
ptrdiff_t minimum width 16 | the requirement fell from 17 | chapter 27 |
| width exception for extended integer types | allows things like int128_t | chapter 28 |
Table 105.1 — What C23 added to the language
The preprocessor#
| What | In brief | Where |
|---|---|---|
#embed | bring binary data into the source as it is | chapter 61 |
__VA_OPT__ | handles the empty variadic case | chapter 61 |
__has_include | asks whether a header is there | chapters 51 and 86 |
#elifdef, #elifndef | the short form of #elif defined | chapter 61 |
#warning | says something without failing | chapter 61 |
one-argument static_assert | the message may be left out | chapter 80 |
Table 105.2 — What C23 added to the preprocessor
The library#
| What | In brief | Where |
|---|---|---|
<stdbit.h> | counting and rotating bits became standard functions | chapters 51 and 83 |
<stdckdint.h> | arithmetic that reports overflow as a value | chapters 54 and 86 |
unreachable | promises that control never comes here | chapter 54 |
memset_explicit | an erase the optimiser may not remove | chapter 70 |
memalignment | asks a pointer for its alignment | chapter 67 |
| qualifier-preserving search functions | put in a const, get a const back | chapter 70 |
free_sized, free_aligned_sized | tell the allocator the size you know | chapter 89 |
realloc(p, 0) is UB (undefined behavior) | an old grey zone moved outside the contract | chapter 46 |
several time bases, timespec_getres | a monotonic clock, and asking its resolution | chapter 79 |
timegm | the UTC counterpart of mktime | chapter 79 |
mbrtoc8, c8rtomb | the UTF-8 pair <uchar.h> was missing | chapter 75 |
call_once mandated | no longer optional | chapter 84 |
POSIX functions folded in (strdup and others) | custom became standard | chapters 69–70 |
length modifiers for intN_t | printf and scanf know the fixed-width types | chapter 66 |
binary integer I/O %b | prints and reads 0b | chapter 51 |
| per-header version test macros | a header states what it has | chapter 19 |
DECIMAL_DIG obsolescent | the per-type macros take over | chapter 28 |
_Imaginary_I qualifiers adjusted | a small repair in an optional header | chapter 83 |
| harmonised with IEC 60559 | follows the floating-point standard more closely | chapter 52 |
| effective-type rules made precise | the ground of aliasing grew clearer | chapter 40 |
Table 105.3 — What C23 added to the library
How to use these tables#
- To skim only what is new — follow the “Where” column of the three tables above and you have gone once around C23.
- To check your compiler keeps up — read chapter 19′s edition table together with
__STDC_VERSION__and the per-header version macros. ★ Being in the standard is not being in the compiler — chapter 87 measures two compilers ignoring[[unsequenced]]. - To move old code over — the last section of chapter 87 sets out an order.