The Birth of C

Almost every program you'll run today sits on top of C. The Linux kernel is written in it. So are the Windows and macOS kernels, the C library every other language calls into, the Python and Ruby interpreters, SQLite, nginx, OpenSSL and Git. It's fifty years old, it lets you shoot yourself in the foot in ways modern languages won't, and this February the White House asked the software industry to start moving off it.

It also exists, more or less, because of one operating system that needed it.

BCPL, B, and a machine with bytes

The family tree starts in 1967 with BCPL, a language Martin Richards designed at Cambridge for writing compilers. It had one data type, the machine word, and it was small and easy to port.

When Ken Thompson wrote the first Unix on a PDP-7 in 1969, he wrote it in assembly language, but he wanted a higher-level language for the tools. He stripped BCPL down to fit the PDP-7's tiny memory and called the result B. Like BCPL, it had no types. Everything was a word.

That worked on the PDP-7. It didn't work well on the PDP-11 that Unix moved to in 1970, because the PDP-11 addressed memory in bytes, had different-sized integers, and was getting floating-point hardware. A language that only knew about words couldn't express that efficiently. Starting around 1971, Dennis Ritchie added types to B: char, int, arrays, pointers and then structures. Around 1972 the language had changed enough to deserve a new name. Ritchie, with a wry sense of sequence, called it C.

Rewriting the kernel

The decisive moment came in 1973. Ritchie and Thompson rewrote the Unix kernel itself in C, and Version 4 Unix shipped that November with most of its kernel in a high-level language. Operating systems simply weren't written that way then. They were written in assembly, for one machine, and they died with it.

A Unix written in C could move to a new computer by rewriting the small, machine-specific part and recompiling the rest. Over the next decade it moved to Interdata, VAX, Motorola 68000 and nearly everything else, and C went with it. Every machine that ran Unix needed a C compiler, so every machine got one. Then every programmer on those machines could write portable software in C.

The relationship ran both ways:

  • C was shaped by Unix. It was built to write an operating system, so it can do what an operating system needs: manipulate memory directly through pointers, lay out structures to match hardware registers, and compile to tight code with no runtime to speak of.
  • Unix spread because of C. Portability is what let Unix escape the PDP-11, and C is what made Unix portable. Universities got Unix with source code, so a generation of programmers learned C by reading the most important program written in it.

Why it won

C wasn't the most elegant language of its time. It won for practical reasons that still apply:

  • It's small. The 1978 book that defined it, The C Programming Language by Brian Kernighan and Dennis Ritchie, is about 230 pages. It also made hello, world the first program everyone writes.
  • It maps closely to the hardware. A C programmer can roughly predict the machine code a statement becomes. That made it fit for kernels, drivers and embedded systems in a way higher-level languages weren't.
  • It runs everywhere. C compilers exist for essentially every processor ever made, which is why other languages use the C calling convention as their common ground.
  • It trusts you. No bounds checks, no garbage collector, no runtime. You get speed and control, and you get the consequences.

C was standardized by ANSI in 1989 and has been revised several times since, most recently as C17, with C23 nearly finished.

Thompson and Ritchie received the Turing Award in 1983 for Unix. Ritchie died in October 2011, a week after Steve Jobs. The coverage of the two deaths was not proportionate to their influence.

The bill comes due

The last feature on that list is the problem. Because C trusts the programmer with memory, a single mistake, like writing past the end of a buffer or using memory after it's freed, can let an attacker take over a program. Microsoft and Google have each reported that about 70 percent of their serious security bugs are memory-safety bugs of this kind. Fifty years of exploits, from the Morris worm in 1988 to Heartbleed in 2014, trace back to them.

That's why, on February 26 this year, the White House Office of the National Cyber Director published a report asking software makers to move to memory-safe languages wherever they can: Rust, Go, Java, C#, Swift. C and C++ were the obvious targets.

The most interesting test of that idea is in C's own home. Since Linux 6.1 in December 2022, the kernel has accepted code written in Rust, initially for drivers, as an experiment. The debates on the kernel mailing lists have been heated. Rewriting fifty years of C isn't realistic, and nobody is proposing it. Writing new drivers in a language where whole classes of bugs can't happen is a different matter.

C isn't going away. There are billions of lines of it, and something still has to sit closest to the hardware. But for the first time in its life, it's no longer the automatic choice for new systems code. For a language written to get one operating system off one minicomputer, half a century as the default is a remarkable run.

Since then

Added October 2026. C23 was published as an ISO standard in October 2024. In December 2025, at the kernel Maintainers Summit in Tokyo, the Rust experiment was declared over and a success. Rust is now a permanent part of the Linux kernel, and Android devices are already shipping kernel code written in it.