Skip to content

The C Programming Language

I began learning software development in 2006, and my very first programming language was C. Over the years, I’ve worked with many programming languages, but C remains a powerful language that continues to hold its place alongside Python, C++, and Rust.

C is not difficult to learn. If you already understand the fundamentals of programming logic, you can build a solid foundation in C within a few weeks. More importantly, learning C gives you a deeper understanding of how software works beneath the abstractions. That foundation remains valuable even as programming languages, tools, and technologies continue to evolve.

In this article, I’ll recommend three books to help you go from the foundations of C to modern programming practices. But first, we’ll take a brief look at where C came from and why I still believe C is worth learning after all these years.

Marcos Borges PhD Learning C in 2006
Marcos Borges (me) and my friend Ariane talking about embedded C in 2006.

The C Programming Language is the first book I recommend to anyone learning C. It is often referred to as the K&R book, after its authors, Brian Kernighan and Dennis Ritchie.

The K&R book popularized the tradition of introducing a new programming language with a simple “Hello, world!” program, now almost universal in programming books and tutorials.

The C Programming Language 2nd Edition

The C Programming Language

  • Second Edition
  • By Brian W. Kernighan and Dennis M. Ritchie
  • Released: March 1988
  • Publisher: Pearson
  • ISBN: 9780133086249

The second book I recommend is Effective C by Robert C. Seacord.

While K&R gives you the foundations of C, Effective C focuses on writing robust and secure C programs. It covers topics such as dynamic memory, strings, I/O, the preprocessor, debugging, testing, and program analysis. The second edition is updated for C23.

I found Effective C easier to follow especially when approaching these topics for the first time. For that reason, I prefer reading it next. It builds on the fundamentals while introducing the practices needed to write better C programs.

Effective C 2nd Edition by Robert Seacord

Effective C

  • Second Edition
  • By Robert C. Seacord
  • Released: September 2024
  • Publisher: No Starch Press
  • ISBN: 9781718504127

My third recommendation is Modern C by Jens Gustedt.

After learning the foundations and getting comfortable writing C, Modern C is a good next step. It goes deeper into the language and its evolution, with particular attention to modern features and C23.

The third edition is fully revised for C23 and covers its major features, along with topics such as portability, error handling, atomics, and type-generic programming.

I found Modern C more challenging to read than Effective C, so I would not necessarily recommend it as the first modern C book for a beginner. Instead, I prefer this progression: start with K&R, move to Effective C, and then use Modern C to go deeper into C23.

Modern C 3rd-Edition by Jens Gustedt

Modern C

  • Third Edition
  • By Jens Gustedt
  • Released: August 2025
  • Publisher: Manning
  • ISBN: 9781633437777

During the 1940s and 1950s, computers were programmed directly in machine code, represented by long sequences of numbers. For instance, a simple program to add 3 and 5 might look like this:

; Load the value 3 into the AL register
10110000 00000011
; Load the value 5 into the BL register
10110011 00000101
; Perform the addition
; AL = AL + BL
00000000 11011000

To make programming easier, assembly language emerged in the early 1950s with symbolic mnemonics such as MOV and ADD. These replaced raw binary instructions, allowing us to express the same operation in a much more readable form:

; Load the value 3 into the AL register
MOV AL, 03h
; Load the value 5 into the BL register
MOV BL, 05h
; Perform the addition
; AL = AL + BL
ADD AL, BL

By the late 1950s, high-level languages such as Fortran (Formula Translation) and ALGOL (Algorithmic Language) had emerged, allowing programmers to write more human-readable code that could then be compiled into lower-level instructions.

Here is a simple example of adding 3 and 5 in ALGOL:

INTEGER a, b, sum;
a := 3;
b := 5;
sum := a + b;

In 1966, Martin Richards designed BCPL (Basic Combined Programming Language) at the University of Cambridge. It was intended to provide a small, portable language suitable for writing compilers and system software. BCPL was typeless, with values represented as machine words, giving programmers considerably more low-level flexibility than languages with more rigid type systems.

Here is an example of adding 3 and 5 in BCPL:

LET A = 3
AND B = 5
AND SUM = 0
SUM := A + B

By 1969, at Bell Labs, Ken Thompson began developing the UNIX operating system on the resource-constrained PDP-7 minicomputer. The initial system was written in assembly language. Thompson soon needed a higher-level language, but found BCPL too large for the PDP-7’s limited memory.

PDP 7
PDP-7 (Programmed Data Processor-7).

To work around the PDP-7’s memory limitations, Thompson created a simplified language based on BCPL and called it B. B was small enough to run on the PDP-7, but like BCPL, it was typeless. This became increasingly limiting as the system grew more complex.

Here is an example of adding 3 and 5 in B:

a = 3;
b = 5;
sum = 0;
sum = a + b;

Between 1969 and 1973, Dennis Ritchie developed C at Bell Labs, building on B, which had been developed by Ken Thompson for the PDP-7. Ritchie then developed C further on the PDP-11. C retained the simplicity of B while introducing data types, structures, and more powerful operators. This gave programmers both low-level control, similar to assembly language, and the higher-level expressiveness associated with languages such as ALGOL and Fortran.

Dennis Ritchie Ken Thompson PDP 11
Dennis Ritchie and Ken Thompson working together at a PDP-11.

C quickly became an important part of the UNIX project. In 1973, UNIX was largely rewritten in C, demonstrating that a systems programming language could provide both the control needed for operating-system development and the portability needed to move the system to different machines.

From there, C became one of the foundational languages of modern computing and continues to be widely used in operating systems, embedded systems, databases, compilers, games, and many other software systems.

Here is how to add 3 and 5 in C:

int a = 3;
int b = 5;
int sum;
sum = a + b;

So, is C still worth learning?

After almost two decades of working with software, my answer is yes.

Every few years, new technologies make older ones look obsolete. We are often told that only the newest languages, frameworks, and tools are worth learning, and sometimes that even writing code itself is becoming obsolete.

I don’t believe we should listen to that.

Technology changes, but the foundations remain. Learning C forces you to understand memory, data representation, pointers, compilation, linking, and the boundary between software and hardware. These concepts don’t become irrelevant when a new technology comes along. They become part of your foundation as a software engineer.

This doesn’t mean you should ignore modern technologies. Learn them, experiment with them, and use the best tools for the problem you’re solving. But don’t give up on the fundamentals simply because something else can do a particular task better or faster.

There are still countless difficult problems waiting for us to solve, and many of them require understanding what happens beneath the abstractions.

So, if you’re thinking about learning C, don’t hesitate.

Just start.

You don’t need to become a C programmer for the rest of your career. Learn it because it will challenge you, make computing less mysterious, and give you a stronger foundation for whatever you decide to learn next.

And if you know someone who is thinking about learning C, send them this article. Maybe it’ll save them a few years of figuring out which books to read first. 🙂