Proven C Book←↑→

Preface

This book is an introduction to the C language, and it is also an introduction to proven, a C library I wrote. There is a reason it serves both purposes.

Before you can recommend a tool, you have to show why it is needed. The problems proven addresses live in the subtle corners of C — the limits of representation, the rules of conversion, the lifetime of storage, the areas the standard declines to promise anything about. To those who have not seen those corners, proven looks like an unnecessary contraption. To those who know them well, on the other hand, their own ways of handling those problems already exist, and there is little reason to reach for proven.

So I decided to explain the problems first and the library afterwards. With a first-time reader in mind, the book begins with how a computer is built and goes on through types and flow, pointers and arrays, the lifetime of storage and the standard library. Having read those earlier parts you may well decide you do not need proven — and that is a fine outcome too. Either way, they will have helped you understand C better and use it more safely.

In truth the library and the book start from the same place and aim at the same thing: to lift the way C is written, and the habits around it, up to what our time calls for. The book supplies the underlying knowledge; the library proposes new coding habits. They only take different roads to the same goal.

C has a long history, and in it are all sorts of scars and contortions and serious deliberations, each an attempt to get past the real limits and difficulties of its time. Tracing those marks has been an interesting and enjoyable thing to do, so adding my own effort to them was the natural next step. The purpose is the one just described, but that proven exists, and that this book exists, comes in the end less from necessity than from a liking for C; I will not pretend otherwise. That liking has spilled over into rather more explanation and rather more pages than strictly needed, and for that I ask the reader’s indulgence in advance. The thickness, well past 1,000 pages (and likely to grow), is the evidence, and half of the book’s limits, set out in the next section, follow from it.

My thanks go to everyone who reads this. That someone spends their time reading my work and adding their thoughts to it is always a happy thing.

What this book intends, and how to use it#

One thing must be clear first. Reading alone will not grow your ability to program. This book has no exercises, no assignments, no “try it yourself”. It sets out a situation, asks a question, and gives an answer to it — that is all. What it intends is that the reader end up with a firm grounding in C, and with a feel and an eye for the traps and dangers built into it. That is somewhat different from the ability to actually produce code: standing in front of an empty file and breaking a problem into pieces, digging out the name of a function that will not come to mind, clearing the errors a compiler has poured out one by one, narrowing down the cause when the output is not what you expected. That grows only by writing it yourself. This book does not do that work for you, and I will not claim it can. That part has to continue in some other course of practice, or in small programs of your own.

That is a flaw in the book, and also a deliberate choice. Above all there was no room. The explanation alone runs past 1,000 pages — the very excess the preface asked indulgence for — and had exercises and assignments gone in too, the book would have doubled and the reader’s burden with it. I chose the side that gets read to the end without strain, and gave up drill in exchange. This is a book for understanding, not a book for making something quickly.

Even so, I think the book keeps its place when that drill is done elsewhere, because C has almost no safety net. In another language a mistaken idea is stopped on the spot by the compiler or the runtime; C mostly accepts it and returns a plausible answer — which is to say that a wrong understanding survives without any signal that it is wrong. So moving your hands first, on thin ground, makes the drill expensive. The same thing takes more time and more trial and error to learn, and worse, a misconception hardens along the way. A hardened misconception becomes a bug later, and sometimes a security vulnerability. A firm foundation cannot do that drill for you, but it makes it far cheaper.

I should also say in advance that the first program comes late. Hello, world does not appear until Part III. Until then the book lays the groundwork — how a computer is built, how storage is divided, how numbers and letters are represented. There is a reason it comes late. Parts I and II are not background thrown in beside the subject; they carry weight of their own, and I think they are the most valuable part of this book. Most of what C looks like comes from what those two parts are about — how a machine handles memory, what can and cannot be represented, and what translation does. So to a reader who is short of time I would say this: skip everything else if you must, but read Parts I and II. And once you have, a fair number of the questions waiting further on — why integers wrap, why the end of a string is invisible, why the compiler does not do what you wrote — will come loose on their own, without being taught. A reader in a hurry to build something may of course find this order slow-going. Such a reader may read chapter 16, hello world, first and come back to chapter 1. The standard this book was written to is reading it in order, but take from it what suits your level and your purpose. To help with that choosing, the pages that follow set down shortcut paths by level.

What the book intends is a firm foundation: not a quick result but an understanding that lasts. Skills picked up from other books and courses sit far more steadily on top of it. The gap between someone who knows why integers wrap, why a pointer is not simply a number, and what a compiler does and does not promise, and someone who does not, only widens with time.

Every piece of code in this book has actually been compiled and run. The printed output is not transcribed by hand: it is what the machine produced when the examples were run during the build. gcc is the base and every example passes under it; clang is used as a cross-check, with seven exceptions. Four are examples whose whole point is the situation clang diagnoses (silencing the warning would blunt the lesson), and three need something that toolchain does not have (a GCC-only switch, the ASan runtime). What is skipped, and why, is written down in the repository.

One more disclosure. This book was written with AI as an assisting tool. What to cover and in what order, which principles the exposition follows, what to include and what to leave out — all of that I decided; the manuscript was written to those instructions and then reviewed by me. Technical claims were checked against the standard and primary sources, and, as said above, the examples are verified by a machine that actually runs them on every build — which means that whether a human or an AI wrote it, code that does not run does not appear in this book.

Errors will remain nonetheless. Those are mine, not the tool’s. If you find one, please tell me.