77 The standard library at a glance
What to know first
Looking back
Chapter 76 said the standard library is “thin and old”, and that the standard pins down not only the grammar but the list of libraries and the contract of each function. Then exactly how many headers are there, and how has that list grown?
A. Thirty-one as of C23. C89 began with fifteen, C95 added two concerning wide characters plus <iso646.h>, C99 six, C11 five, and C23 two. That the speed of growth is almost the same as the language’s speed of change tells the character of this list — once something enters it stays effectively forever, and so it takes long to let anything in. It is the other side of the story of gets’s funeral taking decades (chapter 44).
The need for this chapter, and its context
By the end of this chapter
The questions this chapter answers
- How many of these are actually used often?
77.1 Freestanding and hosted — two worlds#
The standard divides implementations in two. A hosted implementation is the ordinary environment running on top of an operating system, and a freestanding implementation is an environment with no operating system — firmware, a kernel, a bootloader.
The difference between the two is exactly the difference in the header list. The headers a freestanding implementation must accept are the following ten (nine through C11); the rest may or may not be there — though C23 added parts of headers on top. We pick that up after the table.
| header | what | note |
|---|---|---|
<float.h> | the limits of real types | defines values only |
<limits.h> | the limits of integer types | defines values only |
<stdarg.h> | variadic arguments | chapter 67 |
<stdbool.h> | bool | C99. effectively unnecessary in C23 |
<stddef.h> | size_t, NULL, offsetof | the most basic of the basics |
<stdint.h> | fixed-width integers | C99 |
<stdalign.h> | alignas, alignof | C11. keywords in C23 |
<stdnoreturn.h> | noreturn | C11. deprecated in C23 |
<iso646.h> | alternative spellings such as and, or | C95 |
<stdbit.h> | bit manipulation | added in C23 |
Table 77.1 — The headers every freestanding implementation must provide
That C23 lengthened this list is worth noticing. The newcomer <stdbit.h> is pure computation needing no operating system, so it can be provided in a freestanding environment too, and what it does (counting bits) is especially handy in embedded work. That the list grows in the direction of “what works without an OS” shows this division’s character too.
★ The similarly named <stdckdint.h> (checked arithmetic, chapter 96) is not on this list. C23 added exactly one header to C11′s nine — <stdbit.h> — and its other addition is not a whole header but the “require only part of one” of the next paragraph.
And a whole header being required differs from only some of its declarations being required. C23 uses that second way. Beyond the ten headers above, §4p7 requires <string.h> — minus six functions (strcoll, strdup, strerror, strndup, strtok, strxfrm) — and from <stdlib.h> requires exactly one function, memalignment. Look at the six that were taken out and the reason shows: they lean on the locale (strcoll, strxfrm, strerror), they need an allocator (strdup, strndup), or they carry hidden state (strtok). It is the list with only what cannot be done without an OS taken out.
Floating point is conditional too. If an implementation defines __STDC_IEC_60559_BFP__ or __STDC_IEC_60559_DFP__, then <fenv.h>, <math.h> and the strto* family must be usable in freestanding as well (§4p8).
That this list is short is the background of this whole book — in embedded work neither printf nor malloc is a given (the freestanding story of chapter 114 begins here).
77.2 The whole list#
Every header the standard settles. “Edition” is the edition in which that header entered the standard, and the chapter that treats it is written alongside — sometimes a chapter outside this part.
| header | edition | what it holds | where it is covered |
|---|---|---|---|
<assert.h> | C89 | assert — the diagnosis that catches contract violations | chapter 90 |
<complex.h> | C99 | complex arithmetic | chapter 93 |
<ctype.h> | C89 | character classification and conversion | chapter 82 |
<errno.h> | C89 | the error-number global | chapter 90 |
<fenv.h> | C99 | the floating-point environment (rounding, exceptions) | chapter 88 |
<float.h> | C89 | the limits of real types | chapters 28 and 88 |
<inttypes.h> | C99 | formats and conversions for fixed-width integers | Appendix B, chapter 93 |
<iso646.h> | C95 | alternative spellings of operators | Appendix D |
<limits.h> | C89 | the limits of integer types | chapter 28 |
<locale.h> | C89 | locale settings | chapters 83–84 |
<math.h> | C89 | mathematical functions | chapter 88 |
<setjmp.h> | C89 | non-local jumps | chapter 92 |
<signal.h> | C89 | signal handling | chapter 91 |
<stdalign.h> | C11 | specifying and querying alignment | chapter 97 |
<stdarg.h> | C89 | variadic arguments | chapter 67 |
<stdatomic.h> | C11 | atomic operations | chapter 95 |
<stdbit.h> | C23 | bit manipulation (counting, rotating and so on) | chapter 53 |
<stdbool.h> | C99 | bool, true, false | chapter 97 |
<stdckdint.h> | C23 | arithmetic that checks for overflow | chapters 56 and 96 |
<stddef.h> | C89 | size_t, ptrdiff_t, NULL, offsetof | chapter 27 |
<stdint.h> | C99 | fixed-width integer types | chapters 28 and 93 |
<stdio.h> | C89 | stream input and output, files | chapters 78–79 |
<stdlib.h> | C89 | conversion, random numbers, allocation, sorting, program termination | chapter 81 |
<stdnoreturn.h> | C11 | noreturn | chapter 93 |
<string.h> | C89 | strings and memory blocks | chapter 80 |
<tgmath.h> | C99 | type-generic mathematical functions | chapter 88 |
<threads.h> | C11 | threads, mutexes, condition variables | chapter 94 |
<time.h> | C89 | time and the calendar | chapter 89 |
<uchar.h> | C11 | UTF-16 and UTF-32 character types | chapter 85 |
<wchar.h> | C95 | wide-character input, output and strings | chapters 85–86 |
<wctype.h> | C95 | wide-character classification | chapter 82 |
Table 77.2 — Headers added by edition
Q. How many of these are actually used often?
A. Most programs live on about five — <stdio.h>, <stdlib.h>, <string.h>, <stdint.h>, and as needed <math.h> or <time.h>. The rest are things you “know exist and look up when needed”. So this part’s aim too is not memorising but keeping the whole shape in your head — roughly what is where, and which regions are slippery.
A common misconception. “If it is in the standard library it is a safe and portable function”
gets was in the 1989 standard and was deleted only in 2011 (chapter 79). strncpy, contrary to its name, is not a safe copying function (chapter 80), and atoi has no way at all to report failure (chapter 81). The same function can even behave differently according to the locale (chapter 82). Using the standard library means not “using what has been verified” but “using what has a stated contract”, and reading that contract is still our part.In practice. The accident one header caused — <strings.h> is not standard
<string.h> is standard but <strings.h> (plural) is POSIX. Functions such as strcasecmp and bzero are in there, so code using it does not compile on Windows. Conversely strlcpy and strlcat came out of OpenBSD and spread to several Unixes but were not standard — only in C23 were functions of similar intent so much as discussed. The guess “it is used a lot, so it must be standard” is a common beginning of portability accidents.Recap
| to remember | the point |
|---|---|
| number of headers | thirty-one as of C23. grown from C89′s fifteen |
| freestanding | only ten headers are guaranteed without an operating system (C23 added one, <stdbit.h>, to C11′s nine) |
| speed of entering the standard | slow. the speed of leaving is slower |
| standard = safe | no. standard = the contract is written down |
<strings.h> | not standard (POSIX). do not be fooled by the name |
Table 77.3 — The standard library at a glance — what to remember
The shape is laid out, so we walk. The next two chapters are the region used the most and where people slip the most — stream input and output.