the building blocks are so simple and transparent
that you can follow the thread of execution with
minimal mental overhead.
I do not agree.I've seen plenty of code that does weird things with pointers, like passing around a reference to a struct's member, then to retrieve the struct decrementing a value from the pointer + casting. Or XOR-ing pointers in doubly-linked lists for compression. And these are just simple examples.
I've seen code where I was like "WTF was this guy thinking?".
My biggest problem with C is that error handling is non-standard. In case of errors ome functions are returning 0. Some are returning -1. Some are returning > 0. Some are returning a value in an out parameter. Some functions are putting an error in errno. Some functions are resetting errno on each call. Some functions do not reset errno.
Also, the Glibc documentation is so incomplete on so many important issues that it isn't even funny.
Yes, kernel hackers can surely write good code after years of experience with buggy code that they had to debug.
But for the rest of the code, written by mere mortals, I basically get a headache every time I have to take a peek at code somebody else wrote.