C the language is tiny - types, operators, control flow, functions, pointers. It cannot print, read a file, compare a string, or allocate memory. All of that is the standard library: a set of headers that every conforming implementation ships.
This page is a map. Each section says what a header is for, shows one short working example, and points to the fuller page where one exists.
stdio.h - Input and Output
The header you include first in almost every program. It holds printf and scanf, the FILE type and the file functions, and the safer line-oriented input functions.
The essentials: printf, fprintf, sprintf, snprintf for output; scanf, fscanf, sscanf, fgets, getchar for input; fopen, fclose, fread, fwrite, fseek for files. Deeper coverage lives in printf, scanf, and file handling.
One rule worth carrying: never use gets(). It has no way to know the size of your buffer and was removed from the standard in C11. fgets(buf, sizeof buf, stdin) is the replacement.
stdlib.h - General Utilities
The catch-all: memory, conversions, randomness, process control, sorting.
Highlights: malloc, calloc, realloc, free (see dynamic memory); atoi, atof, strtol, strtod for conversions - prefer the strto* family, which can report failure where atoi silently returns 0; rand and srand (see random numbers); exit, abort, getenv, system; and qsort/bsearch.
string.h - Strings and Memory Blocks
C strings are arrays of char ending in '\0', and every operation on them is a function call.
Two habits keep this header from becoming a source of buffer overflows: always know the destination's size, and remember that strcmp returns 0 for equality - if (strcmp(a, b)) is true when the strings differ. String functions covers the safer strncpy/snprintf patterns in detail.
math.h - Mathematics
sqrt, pow, fabs, floor, ceil, round, fmod, the trig and log families, INFINITY and NAN.
This is the one header that may need a linker flag: on Linux, add -lm at the end of the compile command or the linker reports "undefined reference to sqrt". Full tour in [math functions](/docs/c/math-functions).
time.h - Clocks and Dates
The two offsets in struct tm catch everyone: tm_year counts from 1900, and tm_mon is 0-based. time(NULL) is also the usual seed for srand.
ctype.h - Character Classification
Small, and more useful than it looks. Each function takes a character and answers a yes/no question, or converts case.
The full set: isalpha, isdigit, isalnum, isspace, isupper, islower, ispunct, isxdigit, isprint, plus toupper and tolower.
Notice the (unsigned char) cast. These functions are defined for values representable as unsigned char plus EOF; a plain char is signed on most systems, so a byte above 127 arrives as a negative number and the call becomes undefined behavior. The cast costs nothing and removes the whole class of problem.
And prefer these over hand-rolled tests. c >= '0' && c <= '9' happens to work, but isdigit(c) says what you mean and stays correct everywhere.
limits.h and float.h - The Edges of the Types
How big can an int get on this machine? These headers answer it, and the answers are why portable code asks instead of assuming.
INT_MAX is how you check for overflow before it happens, which matters because signed overflow is undefined behavior rather than a wraparound you can test for afterwards.
stdbool.h and stdint.h - Better Types
C had no boolean type until C99. <stdbool.h> supplies one:
bool, true and false are macros for _Bool, 1 and 0, but they make intent obvious. (In C23 they became keywords and the header is no longer required.)
<stdint.h> gives types with guaranteed widths - essential for file formats, network protocols, and anything embedded, where "an int is probably 32 bits" is not good enough:
The PRId32-style macros from <inttypes.h> expand to the correct printf specifier for each fixed-width type on the current platform - which is the portable way to print them, since %d is right for int32_t on some systems and wrong on others.
assert.h - Checking Your Assumptions
assert(expr) does nothing when the expression is true and aborts the program with a message when it is false.
Compiling with -DNDEBUG removes every assertion, so they cost nothing in a release build. That is also the warning: never put a side effect inside an assert. assert(read_next() > 0) stops reading entirely in the release build, and the resulting bug appears only in production.
Assertions are for your mistakes - conditions that should be impossible if the code is correct. Bad user input is not an assertion; it is an if and an error message.
The Rest, Briefly
<stddef.h>-size_t,ptrdiff_t,NULL,offsetof<stdarg.h>- variadic functions, the machinery behindprintf<errno.h>-errnoplusperrorandstrerrorfor reporting why a call failed<signal.h>- handling signals such as Ctrl-C<setjmp.h>- non-local jumps; rarely the right answer<locale.h>,<wchar.h>,<wctype.h>- locales and wide characters<stdnoreturn.h>,<stdalign.h>,<threads.h>,<stdatomic.h>- C11 additions
Two habits make the library pleasant to use. Read the manual page before guessing at a signature - man 3 strtol on macOS and Linux is authoritative and fast. And check return values: malloc, fopen, and strtol all report failure, and a program that ignores them fails much later and much less clearly.
Frequently Asked Questions
What is the C standard library?
The set of functions, types, and macros that every conforming C implementation provides, grouped into about 30 headers. It covers input and output (<stdio.h>), memory and conversions (<stdlib.h>), strings (<string.h>), maths (<math.h>), time, character classification, and the limits of the numeric types. C has no built-in I/O or string handling - all of it comes from here.
What is the difference between stdio.h and stdlib.h?
<stdio.h> is input and output: printf, scanf, fopen, fgets, FILE. <stdlib.h> is general utilities: malloc and free, atoi and strtol, rand and srand, exit, qsort, bsearch. A typical program includes both.
What does ctype.h do?
It classifies and converts single characters: isdigit, isalpha, isalnum, isspace, isupper, islower, ispunct, plus toupper and tolower. Using them instead of hand-written comparisons like c >= '0' && c <= '9' is clearer and correct for every locale and character set.
Do I need to link anything to use the C standard library?
No, with one exception: the math functions. The standard C library is linked automatically, but on Linux <math.h>'s implementations live in a separate library, so sqrt and friends need -lm at the end of the compile command. Everything else just needs the right #include.