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