Dennis Ritchie: How C Made Unix Portable
September 9, 2026 marks 85 years since Dennis Ritchie’s birth. His work on C and Unix changed how software could move between machines—but portable code never meant that every computer could run the same file.

Imagine handing a friend a disk containing your program. Their computer has a different processor, a different operating system and a different idea of how files should work. What have you actually given them: something they can run, something they can rebuild, or an expensive rewriting project? That question makes a better introduction to Dennis Ritchie than a list of famous products that somehow owe him a debt.
The Heidelberg Laureate Forum records his birth on September 9, 1941. Today marks 85 years since that date. The occasion also appears in the Nerd Calendar. Our birthday question is about the work that survives when the original computer does not.
C and Unix solved different parts of the problem
C is a programming language: a way of describing operations that a compiler can translate. Unix is an operating system: it manages resources and gives programs services. Confusing the two hides what made their relationship productive. A language can express a calculation without knowing the model of disk drive. An operating system can offer file access while hiding much of the machinery involved.
The Computer History Museum credits Ritchie with creating C and cocreating Unix with Ken Thompson. Its account places both at Bell Labs in the early 1970s. This was collaborative systems work, not a lone inventor producing every layer of computing.
Think of a program as three connected decisions: what it should calculate, how it requests services, and which machine instructions execute it. Those decisions can be tightly tangled. They can also be separated enough that changing one does not force you to discard the other two. Portability starts with making that separation useful.
The 1973 rewrite was a beginning, not a magic switch
Ritchie and Thompson’s Unix system paper dates the rewrite in C to summer 1973. The archived text is the revised 1978 version of their 1974 article. It describes a system that became easier to understand and modify, despite growing in size.
Rewriting a kernel in a higher-level language changes what a programmer spends time describing. Assembly language closely follows a processor’s instructions. C lets the programmer describe functions, data and control flow while the compiler handles many instruction-level choices. The machine still matters; fewer routine details need to be expressed directly in the main source.
Nor was portability the original master plan. In his history of C, Ritchie says interest in it came later. C evolved from B; 1972 was its most creative year. The story is one of improving a working environment, then discovering how much further it could travel.
Portable source is not a universal executable
Return to that disk. It might contain source code, readable instructions in C. Or it might contain an executable, already translated for a particular target. These are different gifts. A compiler for another target can generate different machine code from suitable source. Copying the old executable does not perform that translation.
Imagine a tiny program that reads temperatures and reports the smallest value. The comparison logic needs no knowledge of a graphics card. If input and output use facilities available on both systems, the same source may be rebuilt for each. Add a window using a platform-specific graphics library, however, and that part introduces another dependency.
A successful compilation is only one checkpoint. The program also needs the expected libraries, input conventions and behaviour. A file that opens successfully can still contain numbers in an unexpected format. Two programs that both launch can still disagree about what the data means. Portability therefore needs a behavioural test, not merely a compiler’s approval.
What must change when the hardware changes?
A useful way to read a program is to ask where it makes promises about its surroundings. Three places deserve particular attention:
- Data representation. Does the program assume a particular integer size or save a structure by copying its raw memory? A defined exchange format is a different thing from an in-memory arrangement.
- Operating-system services. How does it obtain files, time, input and other resources? A narrow interface is easier to adapt than platform calls scattered through every function.
- Hardware access. Code that touches a device directly must understand that device. Moving it behind a clear boundary concentrates the work; it does not make the work disappear.
These questions are our practical reading framework, not a claim that every old C program followed it. A language provides opportunities for separation. Programmers still have to use them. A wonderfully compact program can be full of hidden assumptions, while a slightly longer one can state its expectations clearly.
The real achievement: less rebuilding of human work
In their 1978 paper on C and Unix portability, Stephen C. Johnson and Ritchie document the move to the Interdata 8/32. Their practical measure is effort saved compared with rewriting. Much of the source remained common across environments; the surrounding engineering still mattered.
That is the perspective worth keeping. The prize is not the absence of all adaptation. It is preserving the part of a program that already embodies thought: its algorithms, decisions and accumulated understanding. A new machine should not automatically mean solving the same problem from the beginning.
There is a useful companion story in our article about Steve Wozniak’s personal-computer engineering. Read the two together as different design questions: how do you make a machine approachable, and how do you keep useful software from being trapped inside one machine?
Read this article in: German · Spanish · French.
A birthday exercise: find one hidden assumption
You do not need to port an operating system to try this idea. Take a small program you understand. Write down its expected input and output, then identify one assumption about the environment. It might be a directory path, a character encoding or a particular screen library.
Move that assumption into a clearly named boundary. If a second environment is available, rebuild there and compare results using the same examples. If it is not, document what would need checking. This does not prove universal portability. It turns a vague ambition into a specific question someone else can investigate.
On Ritchie’s 85th birth anniversary, that is a fitting tribute: make one piece of knowledge easier to carry forward. C and Unix did not abolish differences between computers. Their history shows why reducing the cost of those differences can matter more than pretending they do not exist.
