C's standard library is organized into small, focused headers rather than one large namespace: stdlib.h holds general-purpose utilities (memory allocation, string-to-number conversion, sorting, program termination), ctype.h classifies and transforms individual characters, math.h provides floating-point functions like sqrt and pow, and time.h handles dates and times. Compared to languages with large batteries-included standard libraries, C's is deliberately minimal — no built-in networking, JSON, regular expressions, or containers beyond raw arrays — reflecting a design philosophy that anything not genuinely universal belongs in a third-party library instead.
stdlib.h: the general-purpose toolbox
atoi silently returns 0 on genuinely invalid input, with no way to distinguish "the string was \"0\"" from "the string wasn't a number at all" — strtol (also in stdlib.h) is the more robust alternative when that distinction matters.
#include <stdlib.h>
#include <time.h> // time() lives here, not in stdlib.h -- Clang treats the
// missing include as a hard error ("call to undeclared
// function"), GCC only warns and guesses the return type
int n = atoi("42"); // string to int — but silently returns 0 on invalid input too
double d = atof("3.14"); // string to double
srand(time(NULL)); // seed the random number generator
int r = rand() % 100; // pseudo-random number, 0-99
exit(1); // terminate the program immediately with status code 1ctype.h: classifying individual characters
These functions take an int (a char value, effectively) and return nonzero for true, 0 for false — genuinely useful building blocks for hand-writing a parser or validator without pulling in a bigger library. The standard is explicit that the behavior is undefined if the value passed isn't representable as unsigned char or equal to EOF — so a plain char value, which is signed on most platforms (gcc/clang on x86/ARM Linux default to signed char), needs an explicit cast before going in. 'A' is positive either way so this specific example is safe, but any byte above 127 (extended/non-ASCII input) would be negative as a plain char and genuinely UB without the cast — cast to unsigned char as a habit, not just when it happens to matter.
#include <ctype.h>
unsigned char c = 'A'; // unsigned char, not char -- ctype.h functions are UB on a
// negative value, and plain char is signed on most platforms
if (isalpha(c)) { printf("letter\n"); }
if (isdigit('5')) { printf("digit\n"); }
char lower = tolower(c); // 'a'math.h: floating-point functions
Linking math.h's functions historically required an explicit -lm flag on the compile command on some systems (particularly older Linux toolchains) — worth knowing if a program compiles with a mysterious "undefined reference to sqrt" error despite including math.h correctly.
#include <math.h>
double root = sqrt(16.0); // 4.0
double power = pow(2.0, 10.0); // 1024.0
double rounded = round(3.6); // 4.0
// compile with: gcc -o app app.c -lm (the -lm may be required on some systems)