An Interview with Brian Kernighan on C and The C Programming Language
informit.com
informit.com
The language is simple enough that you're left with nothing to get in the way of the problem in front of you, and you're forced to think of what is happening on a very low level.
That low level understanding helped when I tried languages with more abstractions.
ꙮ I always use enum instead of #define for numeric constants.
ꙮ I nearly always use inline instead of #define for small functions whose efficiency worries me.
ꙮ As a result of those two things, I don't use #define much.
ꙮ Everything global is static unless it's in the public API provided by the file.
ꙮ I use dynamic allocation a lot more than the C in the K&R book.
ꙮ I avoid integer function arguments and return values as much as possible, because they're basically untyped, and I benefit from the limited static type checking done by C compilers. I still use them for cases where I'm actually counting or measuring something, and unfortunately for bitfields. When I'm counting bytes, the correct type is usually size_t or ptrdiff_t, which benefits humans and LP64 platforms, but doesn't get you much static type checking benefit.
ꙮ As a result of those two things, I use arrays relatively sparingly.
ꙮ I basically never use function-static variables because they make thread-safety very difficult if not impossible.
ꙮ Use const wherever applicable. It catches some errors, and it's not nearly as draconian as in C++, so it doesn't cause as many problems.
ꙮ After some experience with C++, I usually "typedef struct foo foo", since it costs me two words in the declaration and saves me the "struct" every time I use "foo" later.
I don't know if these are the kinds of things people mean when they talk about new ways of coding in C, or where to find them documented.
What do you think is the minimum realistic preprocessor usage that can be got away with? #include + #pragma once?
For me, container_of() is also indispensable. Although maybe it's on the level of 'errno' as being "not really a dirty macro".
I'm new to C (and very much a self-taught amateur), but what's the advantage of this? (No snark - I just don't see it.)
I have a file at hand with this:
#define MAXLINE 512
How would that be improved by putting it in an enum instead? max_line = 512,
than in #define MAXLINE 512
but I agree that the difference is small. In some cases, your code is more readable if you can define more than one constant per line, and the difference becomes larger: min_x = 20, min_y = 20,
max_x = 8.5*72 - 20, max_y = 11*72 - 20,
Beyond that, non-anonymous enums have the additional advantages that you can define them closer to where they're used, and the debugger knows how to print them.I just want to emphasize this point, as this is the main advantage in my eyes.
Given that Kernigham and Ritchie were using C to write an OS, it's not surprising that they'd be wary of dynamic allocations.
Dr. Dobbs did a nice series on C99 features, so I'd recommend that as a supplement to K&R.
http://www.drdobbs.com/the-new-c-compound-literals/184401404
However, I've kept an eye on the C99 and C11 standards processes, and at least in Germany there are a few authors with books about those standards.
But it is not the same as having the famous C book updated to the latest standards. Mainly as a collector item, in my case.