Before any formal standard existed, Kernighan and Ritchie's 1978 book "The C Programming Language" served as the de facto specification, a dialect now called K&R C. ANSI formally standardized the language in 1989 (ANSI C, also called C89), adopted internationally by ISO the following year as C90. Since then, C99 (major update: // comments, variable-length arrays, designated initializers), C11 (added _Generic, atomics, optional threading), C17 (a bugfix-only release, no new features), and C23 (finalized 2024, adding nullptr, real bool/true/false keywords, and binary literals) have each incrementally extended the language while preserving C's strong backward-compatibility tradition.
C99: the first major post-ANSI overhaul
// line comments (previously only /* */ was legal), declaring variables anywhere in a block rather than only at its start, and variable-length arrays were all genuinely significant, widely-used additions.
// line comments — illegal before C99, only /* */ was standard
void process(int n) {
int arr[n]; // variable-length array (VLA) — size determined at runtime, added in C99
for (int i = 0; i < n; i++) { // declaring i right here — also a C99 addition
arr[i] = i;
}
}C11 and C17: safer generics, threading, a cleanup pass
_Generic enables genuinely type-generic macros for the first time; C17 (2018) deliberately added zero new features, existing purely to fix defects found in C11 — a fact worth knowing so C17 code isn't mistaken for missing some feature it simply never had.
#define TYPE_NAME(x) _Generic((x), \
int: "int", \
double: "double", \
default: "unknown")
printf("%s\n", TYPE_NAME(5)); // "int"
printf("%s\n", TYPE_NAME(5.0)); // "double"C23: the current standard, finalized 2024
nullptr replaces the historically ambiguous NULL macro with a genuine, distinctly-typed null pointer constant; bool/true/false became real keywords instead of stdbool.h macros — both changes covered in the earlier control-flow topic, and both examples of C slowly closing long-standing rough edges while never breaking existing code.
int *p = nullptr; // C23: a real, distinctly-typed null pointer constant
bool ready = true; // C23: bool/true/false are now built-in keywords, no #include needed