# Sun, 14 Aug 2022 10:13:27 -0500 Here I'm summarizing my thoughts I have from going through the K.N. King Book, it's more of an internal dialog than an explanation of the specific C features (and that would take too long and I already have notes), but there are flash-cards below as a reward for the reader and an explanation of what's next at the botom, so:

Language

I think the main benefit of going through this book was clarifying exactly how C is different than C++, some main surprising parts are, for example, how array types decay into pointers as function parameters and act as constant lvalues, and the exact semantic meaning of struct tags vs struct typedefs, which I never had to think about. Designated initializers are cool and fairly flexible. I wouldn't have guessed references to compound literals would be allowed, etc... The book certainly has made me more language lawyery, in addition to caring about semantics of language, standard semantics like "undefined" vs "implementation defined" or "system call" vs "library call". The notion of string literals vs string arrrays. It turns out the lower you go, it doesn't necessarily get much simpler in manageable complexity, but it does get flatter in the abstraction of it. A lot of the terminology is similar and overlaps, but online people seem to use e.g. parameters vs arguments, automatic scope vs linkage terms correctly so I should too for C concepts. Idioms of the language were less surprising, essentially pointers are the main "iterator" type so a lot of idioms match up, but the string/data processing with really clever while loops e.g.
while(*a++ = *b++);
for concatenating null terminated data would have been somethign that'd taken me a couple of minutes to figure out. I also found one valid use of goto's: putting a label after a complex loop with embedded cases that I want to be able to break from without spamming the break statement. Learning about floating point exceptions and how to explicitly ignore them or care about them makes the compiler-related optimizations I was already using make sense.

Libraries

The most excruciating yet goal-important part was going through each std library header piece by piece. I even made flash cards since it was so important and verified anything ambiguous with searches and a small program. This was a pain, but, given how much less expansive and more used the C headers are than the c++ ones, I figured it's much more doable and worth it. The main lesson here was just the error cases for each header being slightly different with each other, and gaining a very concrete idea of what to call and how to do cross-platform i/o. I like C i/o more than C++ because a lot of the ambiguity wrt buffering and casting has been reduced. One of the main takeaways from going over the standard library is how a lot of fancier syntactic features that do the same things as string parsing functions, or memory copying, are unnecessary and take away from what's actually happening, which bites you in the end. Better syntax != better programming. You can always build abstraction up but it's much harder to cool abstraction down. Overall I'm pretty comfortable with the standard library except locale.h, so I don't think I'll be reimplementing any wheels any time soon. other points: Glad I finally understand time.h, and special call-out to setjmp, longjmp. Very fun feature. Here's a link to the flash-cards for those interested: https://mathtools.dev/uploads/C_notes.apkg

Design Concepts

While not the focus of the book, I think it hinted at some good guidelines. In the chapter on program design, I think the fundamental idea of a "module" as a shared object whose interface is the externally linkable components actually simplifies header design. And the 4 categories given for moduiles: data pool, abstract object, abstract datatype, and library cover at least the standard library and all I've used, which is enough to organize a project around. It seems like information hiding is much more emphasized than in C++. A large part of the design guidelines started emerging specifically about what not to do, things to do to avoid conflicts with the C standard and how that could be applied between libraries. A lot of undefined behavior As painful as it is, the C89 differentiation in the book explained some history of the the coding styles I've seen. For example, seeing functions used without declarations in ancient HP-UX code bases, and then later seeing explicitly declared functions with no arguments, e.g.
int givenum(void);
. In-fact a large part of this book felt like a history lesson in how certain types couldn't be assumed some size because of a historical system or mode (e.g. the historical case of short pointers and long pointers). While looking for guidelines for syntax, I noticed a lot of writers try to explicitly write for "C89++" because of the permanence of old code and conventions. e.g. I like the coding style guidelines for suckless https://suckless.org/coding_style/ but I also like the C99 extensions, e.g. complex.h and would want to keep using them.

Conclusion

It was painstaking and certainly not the most efficient use of time from the pov of getting new software written, but I'm glad I went through the book. Now I'll be moving into the next step of the sabbatical and leaning into the C linux API. I'll try to adopt some good practices from writing a python module, then I'll jump right into, not "The Design of the Unix Operating System", but "Understanding the Linux Kernel, Third Edition". Even though it's out of date, I'll try running the examples with an old version in a VM and then when I get to "linux kernel programming", I'll try to adapt it to a modern distribution.