Vai al contenuto principale
Bethemesh
StoriaStoria dell’informatica

The C language: making systems portable without hiding the machine

From BCPL and B to Unix, discover how C balanced portability, efficiency, and hardware control before influencing generations of languages.

Pubblicato 3 agosto 2026Lettura : 5 minDi Bethemesh Team
Principiante
Illustration connecting C source code and a compiler to several hardware architectures
Mostra indice
  1. Before C: BCPL and B
  2. A language shaped by Unix
  3. Rewriting Unix changed the project’s reach
  4. A small syntax, an essential library
  5. From K&R C to an international standard
  6. Why C influenced so many languages
  7. The limits of trusting the programmer
  8. Why C still matters
  9. Timeline
  10. Frequently asked questions
  11. Did Dennis Ritchie create C alone?
  12. Is C portable by nature?
  13. How do C and C++ differ?
  14. Why does C have no garbage collector?
  15. Is C still a good first language?
  16. Will safer languages replace C?

C addressed a concrete problem of the 1970s: how could an operating system remain close enough to hardware for efficiency without being almost entirely rewritten for every new computer?

Dennis Ritchie developed C at Bell Labs in the context of Unix. The language did not try to conceal the machine. It offered a small set of abstractions—types, functions, structures, and pointers—that a compiler could translate efficiently across architectures. That compromise explains both its spread and the memory errors newer languages try to prevent.

Before C: BCPL and B

In the 1960s, systems software was still largely written in assembly. Assembly controlled the processor precisely, but every architecture had different instructions. Porting a program often meant rewriting much of it.

Martin Richards designed BCPL in 1967 as a compact language for compilers and systems. Ken Thompson derived B from it for early Unix. B simplified work compared with assembly, but its essentially typeless model was designed for word-oriented machines.

The PDP-11 on which Unix evolved could address bytes and manipulate several data sizes. Ritchie added types, improved arrays and structures, and gradually transformed “New B” into C between 1971 and 1973.

A language shaped by Unix

C was not designed on paper and then applied to Unix. Language and system evolved together. Kernel needs pushed C to represent addresses, characters, memory blocks, and data structures with little overhead.

A pointer contains a data address. It can traverse an array, construct a linked list, or access a device. Nothing automatically guarantees that the address is valid. Code may read beyond an array, use released storage, or interpret bytes as the wrong type.

The language also leaves details to implementations, including integer sizes, byte order, and structure alignment. Portable code must rely on guarantees defined by C rather than details observed on one machine.

Rewriting Unix changed the project’s reach

In 1973, most of the Unix kernel was rewritten in C. Hardware-specific portions remained in assembly, but most of the system could be recompiled for a new architecture.

This did not make every program automatically portable. Drivers and hardware assumptions still needed adaptation. It nevertheless demonstrated that a performant operating system could be expressed in a higher-level language without becoming captive to one processor.

Unix then spread through universities with its source and tools. Students learned the system and its primary language, wrote software, and carried those practices into industry. C benefited from Unix adoption; Unix became more adaptable through C.

A small syntax, an essential library

C has few built-in constructs. Input and output, string handling, and dynamic allocation mainly come from libraries. This keeps the language core compact and implementable in very different environments.

The standard library nevertheless establishes an essential contract. A function such as fopen prevents every program from needing exact system calls to open a file. Portability therefore rests on three elements: language, compiler, and compatible library.

Compilation generally produces native code. C requires neither a virtual machine nor garbage collection. Programmers control allocation lifetimes, enabling predictable footprints while increasing responsibility for resources.

From K&R C to an international standard

In 1978, Brian Kernighan and Dennis Ritchie published The C Programming Language. It described C precisely enough to become its de facto reference; that form is often called K&R C.

As compilers multiplied, differences appeared. An ANSI committee began defining a common standard in 1983. C89 formalized the language and library, and ISO adopted it in 1990.

Later revisions cautiously added types, concurrency tools, and clarifications. Evolution remains constrained by compatibility because enormous codebases and system interfaces depend on historical C behavior.

Why C influenced so many languages

C++ directly extended C with richer abstractions. Objective-C combined it with a Smalltalk-inspired object model. Java, JavaScript, C#, and Go borrowed much of its syntax without retaining its memory model.

Syntactic influence should not obscure different contracts. Java protects memory through a virtual machine. Rust uses a type system to enforce lifetimes. Go uses garbage collection. Each responds differently to the costs of C’s direct control.

C remains common ground in operating systems, libraries, and embedded environments. Even memory-safe languages often communicate through APIs defined in C.

The limits of trusting the programmer

The C standard defines undefined behavior: after certain rule violations, no outcome is required. Compilers may optimize on the assumption that these situations never occur. The freedom supports performance but makes some errors difficult to predict.

Buffer overflows and lifetime mistakes have caused many vulnerabilities. Compilers, static analysis, runtime protections, and coding rules reduce but do not eliminate risk. C remains relevant where precise control and broad compatibility are essential; that does not make it the default for every application.

Why C still matters

C established an enduring abstraction layer between assembly and high-level software. It describes operations close to hardware in notation shared across architectures.

Its history shows that successful abstraction need not hide every cost; it can make costs manageable. The price of that transparency is discipline that C itself enforces only weakly and that teams, tools, and standards must supply.

Timeline

  • 1967: Martin Richards presents BCPL.
  • 1969–1970: Ken Thompson develops B for early Unix tools.
  • 1971–1972: Dennis Ritchie evolves B into C on the PDP-11.
  • 1973: Most of the Unix kernel is rewritten in C.
  • 1978: The C Programming Language is published.
  • 1983: ANSI X3J11 begins standardization work.
  • 1989: The ANSI C standard is published.
  • 1990: C becomes an ISO standard.
  • 1999: C99 adds new types and numerical features.
  • 2011: C11 introduces, among other things, a concurrency memory model.
  • Today: C remains central to systems, embedded software, and software interfaces.

Frequently asked questions

Did Dennis Ritchie create C alone?

He was its principal designer, but C emerged from Bell Labs’ collective environment through B, Unix, users, and compiler work.

Is C portable by nature?

It enables portability, but programs may depend on hardware details or extensions. Real portability requires following the standard and isolating platform-specific code.

How do C and C++ differ?

C++ derives from C and adds classes, templates, overloading, and deterministic resource management. They now have separate standards and incomplete compatibility.

Why does C have no garbage collector?

Its design favors a small runtime and explicit resource control. Implementations can add collectors, but the standard does not require one.

Is C still a good first language?

It teaches data representation and memory behavior but quickly exposes complex risks. Its suitability depends on the learning objective and domain.

Will safer languages replace C?

Some new projects choose Rust or other languages when memory safety dominates. The scale of existing C code, tools, and interfaces guarantees a long coexistence.

Fonti e riferimenti

  1. 1.Dennis Ritchie --- The Development of the C Language
  2. 2.Dennis Ritchie et Ken Thompson --- The UNIX Time-Sharing System
  3. 3.ISO --- ISO/IEC 9899, langage C
  4. 4.Computer History Museum --- Dennis Ritchie

Raccolta

Linguaggi di programmazione

  1. 01Grace Hopper: from early compilers to COBOL
  2. 02John Backus: FORTRAN, BNF, and the rejection of machine code
  3. 03Dennis Ritchie: the C language at the heart of Unix
  4. 04FORTRAN: proving that a compiler could compete with assembly
  5. 05The C language: making systems portable without hiding the machine
  6. 06Niklaus Wirth: from Pascal to Oberon, designing through simplicity
  7. 07Bjarne Stroustrup: designing C++ without giving up performance
  8. 08Pascal: learning to program by making structure visible
  9. 09C++: from C with Classes to a general-purpose language
  10. 10Object-oriented programming: objects, messages, and reusable abstractions
  11. 11Guido van Rossum: creating Python to make code readable
  12. 12Brendan Eich: JavaScript, from Netscape prototype to Web standard
  13. 13James Gosling: the engineer behind Java
  14. 14Python: readability, batteries included, and a global ecosystem
  15. 15Java: write once, run anywhere
  16. 16JavaScript: the language that made the Web interactive
  17. 17Ken Thompson: from Unix to Go, simplicity as a method
  18. 18John McCarthy: Lisp and the idea of programming with symbols
  19. 19Alan Kay: Smalltalk and the computer as a personal medium
  20. 20Barbara Liskov: the abstraction that made software modular
  21. 21Robin Milner: ML, machine-assisted proof, and languages of interaction
  22. 22Brian Kernighan: AWK, Unix, and the art of explaining code
  23. 23Anders Hejlsberg: from Turbo Pascal to C# and TypeScript
  24. 24Larry Wall: Perl, the language that connected the tools of the Internet
  25. 25Yukihiro Matsumoto: Ruby and programmer happiness
  26. 26Rasmus Lerdorf: PHP and the democratization of the dynamic Web

Questo articolo ti è stato utile?