Verdict: Recommended with reservations
This book presents patterns for C programmers. It was written to answer questions like:
- How to structure a C program.
- How to cope with error handling.
- How to design flexible interfaces.
The author also wrote an article, ‘Fluent C’, in the January 2023 issue of CVu magazine (https://accu.org/journals/cvu/cvu34-6).
Take note – this is not an implementation of the GoF’s Design Patterns – however, another book, Patterns in C by Adam Tornhill is recommended. Adam Tornhill wrote some articles in CVu under the name Adam Petersen, ACCU members can access articles he wrote in CVu magazine (see https://accu.org/journals/nonmembers/cvu_author_neutered/ and https://accu.org/journals/cvu/18/1/cvu18-1.pdf ) The GoF, however, uses its inside front and back covers for reference information as well as citing page numbers for easy Pattern reference. This book does neither. This is material for C programmers and perhaps other programmers wanting a better idea of how things can be done in C. It is not suitable for novices because of sloppy errors. The patterns are provided in a standard format: Name, Context, Problem, Solution, Consequences, Known Uses and, How a pattern can be applied to a running example.
The first part breaks the topic up into 9 chapters, each presenting a Pattern Category along with an overview diagram, showing how patterns are related. Those categories are:
- ‘Error Handling’ or how to clean up resources after an error has been detected.
- ‘Returning Error Information’ or what to return from a function or should you log it instead?
- ‘Memory Management’ – different approaches with pros and cons.
- ‘Returning Data from C Functions’ – ranging from returning by value through to emulated out parameters.
- ‘Data Lifetime and Ownership’ – 4 more patterns on memory management.
- ‘Flexible APIs’ – 4 patterns drawing on SOLID principles
- ‘Flexible Iterator Interfaces’ – 3 different strategies for iterating over a data container.
- ‘Organising Files in Modular Programs’ – 5 patterns for organising your source code files.
- ‘Escaping #ifdef Hell’ – structured use of the C preprocessor.
In the second category, ‘Returning Error Information’ (page 31), the author uses
strcpy() to copy characters into a
char buffer. In an ideal world, he would write his own string copy function – perhaps one that copies a string using
strncpy and then ensure that the buffer is
For reasons unknown to me, the author persists on using
strcmp to check for an empty buffer when you can use something like
if (buffer=='\0') instead. Later on in the book, he uses
fopen without considering it can return a
NULL pointer to indicate an error. Similarly, later on in the book he uses
malloc without checking for a
NULL pointer being returned. He does introduce a function,
safemalloc(), which implements the author’s Samurai Principle (either return victorious or not at all) where the caller’s program is aborted if a
malloc fails. Not sure how good that is in production code.
Most C programmers know to use
#define when using arrays. The author frequently uses this snippet of code:
char dirname; char filename;
Personally, taking https://en.cppreference.com/w/c/io into account, I would have used:
char dirname[FILENAME_MAX]; char filename[FILENAME_MAX];
Additionally, the author’s use of
#defines is a little naive – he uses overly generic names such as
MAX_SIZE, which are more likely to clash with other programmer’s
#defines and convey less meaning to the reader. The author does use
typedef but, uses uppercase for identifiers where I would have used either a mixture of cases or just lower case. Here is an example:
typedef struct INTERNAL_DRIVER_STRUCT* DRIVER_HANDLE;
The second part, ‘Pattern Stories’, provides two case studies – ‘Implementing Logging Functionality’ and ‘Building a User Management System’. They are a good way to exercise the reader’s grasp of the patterns presented in this book but I would hesitate to use them in production code.
The author has a good grasp of the big picture in this book. However, with C Programming, a good understanding of the language and the standard library are critical. In this book, some of the code examples are frequently incomplete, sloppy, or otherwise flawed. He comes from a background in embedded multithreaded real-time environment so this is quite surprising. Sometimes the beauty is in the details. The Patterns in the book are very good. The implementations are not so good.