Skip to main content

The C Standards: K&R, C89, C99, C11

What This Concept Is​

"C" is not one language. It is a sequence of standards, each specifying what a conforming C compiler must accept and what it means.

Milestones you will meet in practice:

  • K&R C (1978) - the language described in the first edition of Kernighan & Ritchie. Old-style function declarations, no prototypes, no void, implicit int.
  • C89 / C90 (ANSI X3.159-1989, ISO/IEC 9899:1990) - the first standard. Prototypes, void, const, volatile, standard library locked in. This is the second-edition K&R book.
  • C99 (ISO/IEC 9899:1999) - // line comments, mixed declarations and code, variable-length arrays (VLAs), inline, long long, <stdint.h>, <stdbool.h>, compound literals, designated initializers.
  • C11 (ISO/IEC 9899:2011) - _Static_assert, _Generic, anonymous structs/unions, atomic types, threads (optional), gets removed, fopen_s/gets_s optional in Annex K.
  • C17 (ISO/IEC 9899:2018) - bug-fix revision of C11, no new features.
  • C23 (ISO/IEC 9899:2023) - nullptr, constexpr, bool as keyword, [[attributes]], binary literals, improved <stdbit.h>. Compiler support is still landing.

For this module, default to C11 with gcc -Wall -Wextra -std=c11. K&R's second edition is your primary text; it tracks C89 closely. Flag anything that requires C99 or later explicitly.

Why It Matters Here​

You will read code from all four eras:

  • legacy embedded and Unix code is often K&R or C89
  • most Linux kernel code is C89 with GNU extensions
  • modern application C targets C99 or C11
  • research and security code is migrating to C11/C17

If you cannot tell which era a snippet is from, you will miss both its bugs and its idioms.

Concrete Example​

Same function, four eras:

K&R style (do not write new code like this):

int sum(a, b)
int a; int b;
{ return a + b; }

C89/C90:

int sum(int a, int b) { return a + b; }

C99 (new features):

int sum(int a, int b) {
int result = a + b;
for (int i = 0; i < 1; i++) { /* mixed decl + code, `int i` in for */ }
return result;
}

C11 (new features):

#include <assert.h>
_Static_assert(sizeof(int) >= 4, "need 32-bit int");
int sum(int a, int b) { return a + b; }

Common Confusion / Misconception​

"// comments have always been in C." They were only standardized in C99. If you see a textbook that rejects them, it is C89 era.

"C and C++ are almost the same." They diverged at C89. Writing in the "common subset" costs both languages their natural idioms. Pick one per project.

How To Use It​

  1. Decide the standard at the start of a project and add -std=c11 (or equivalent) to the build.
  2. When reading older code, silently translate: "implicit int" means "this was C89 or K&R."
  3. When writing, prefer the most recent standard your toolchain supports without compromising portability targets.
  4. Do not mix K&R function definitions with modern prototypes in the same file - most compilers now warn or error on that combination.

Check Yourself​

  1. Which standard introduced // comments, long long, and <stdint.h>?
  2. Which standard removed gets? Why?
  3. What is "implicit int" and why is it dangerous?

Mini Drill or Application​

Given the function int f(a, b) int a; int b; { return a * b; }:

  1. Rewrite it in C89 prototype style.
  2. Rewrite it in C99, and add a _Bool return value for whether the product overflowed.
  3. Add a C11 _Static_assert that sizeof(int) == 4.
  4. Compile each form with gcc -std=c89 -Wall and gcc -std=c11 -Wall and list the warnings.

Read This Only If Stuck​