Verdict: Highly recommended.
I approached this book from the perspective of a C programmer who has programmed in K&R C and C89. I wanted to see what had changed since then and, perhaps, what has happened to the tools available.
It is a fairly accomplished description of the language – there were parts, though, that I read that described things I already knew but found difficult to follow – I found the language of the book a bit ‘wordy’ in parts and better examples and a few extra diagrams would have improved this book. A few changes would have made this book a better initial reference – highlighting gotchas, an overview of the different parts of the standard library and a glossary. The examples are typically fragments – if they had been complete examples which could be typed in and experimented with – or even downloaded and played around with – this would have been a better book for the more inexperienced reader. And there is the occasional typo in the examples.
This book is more up to date than The C Programming Language (2nd Edition). The examples are not as good as that book but, on the other hand, not everyone can write as well as Kernighan and Ritchie. But, this book is more up to date, introduces terminology used by the C standard, has a whole chapter on Program Structure and mentions more tools. It does refer the reader to the C standard but forgets to tell the reader about links to the C draft standard which would have been helpful. Also, the website https://en.cppreference.com/w/c/language is mentioned as a useful reference but, I feel not mentioned enough. Whilst Threads and Atomics are mentioned, they are not covered – no reference given as to where to learn more. I feel this is a pity because these topics are important these days.
The ‘Characters and Strings’ chapter goes way beyond ASCII. Various character sets are mentioned – Unicode, UTF-8 etc and the Bibliography has a link to the rather useful UTF-8 and Unicode FAQ for Unix/Linux: https://www.cl.cam.ac.uk/~mgk25/unicode.html
Over time, common errors have been noticed in C programs. Many string and memory handling functions are too easily misused. Special safe (yet optional!) variants of
strcpy etc are mentioned. I would very much like those functions to be made a required part of the language. Handling Dynamically Allocated memory is covered, along with the use of Gray Watson’s debug memory allocation library (DMALLOC) to debug your programs that use malloc and its siblings.
There are two chapters – ‘Program Structure’ and ‘Debugging, Testing, and Analysis’ that stand out to me as something special, especially for the novice developer.
The ‘Program Structure’ chapter has an interesting multi-file program to type in and experiment with. I think either coverage of Make or more complete coverage of CMake would have been helpful. It does try to be platform-agnostic – covering Windows and *nix tools and command line options.
The ‘Debugging, Testing, and Analysis’ chapter is full of useful information on static and dynamic analysis tools. K&R, notably, did not even mention lint. This chapter more than does that, covering
static_assert, useful (GCC/Clang/Visual C++) compiler settings and flags, Google Test for unit testing (albeit at the complication of using C++ to test C code), AddressSanitizer and a little mention for CMake.
To conclude: A worthwhile addition to a C programmer’s bookshelf.