On Mon, Dec 10, 2012 at 07:37:14PM +0000, David Laight wrote: > On Mon, Dec 10, 2012 at 09:36:35AM -0600, David Young wrote: > > What do people think about setting stricter guidelines for using the > > C preprocessor than the guidelines from the past? Example guidelines: > ... > > 4 Computed constants. The result of a function call may not be used > > in a case-statement, even if the function evaluates to a constant at > > compile time. You have to use a macro, instead. > > The alternative to constants would be C enums. > However C enums are such 2nd class citizens that they have problems > of their own.
I'm not sure you mean quite the same thing. An example of what I mean by "computed constant" would be something like f(Y) where Y is some other constant and f(X) can always be evaluated to a constant at compile time: f() may not be a function, not even a static/inline function, if f(Y) appears in a case statement. (Actually, if f() is an inline function and the compiler optimization level is turned up, GCC will let you put f(Y) in a case statement. Turn the optimization level down, though, and you get a compile error.) > > The C preprocessor MUST NOT be used for > > > > 1 In-line code: 'static inline' subroutines are virtually always better > > than macros. > > That rather depends on your definition of better. It comes down to the ease of reading/understanding/writing a macro like #define M(x, y) \ do { \ ... \ ... \ ... \ } while (0) when something like static inline void M(int x, int y) { ... ... ... } will do. The guideline can be re-phrased, "reach for a function before a hairy macro; use a hairy macro only when nothing else will do." When I say "hairy macro" I mean one like WM_INIT_RXDESC() in sys/dev/pci/if_wm.c: the extra underscores, parens, and backslashes badly clutter the code. Was the same code written as a static or static inline function, first, found wanting, and converted to a macro? Or was the author in the habit of using a macro, first? I'm pretty sure that the code is a macro for the latter reason. > a) #define macros tend to get optimised better. Better even than an __attribute__((always_inline)) function? > b) __LINE__ (etc) have the value of the use, not the definition. I certainly don't want to rule out the careful use of __LINE__ or __func__. > > 2 Configuration management: use the compiler & linker to a greater > > extent than the C preprocessor to configure your program for your > > execution environment, your chosen compilation options, et cetera. > > Avoiding #ifdef inside code tends to be benefitial. > But, IMHO, there isn't much wrong with using #defines in header files > to remove function calls. Example? > Using the compiler gets to be a PITA because of the warning/errors > about unreachable code. I wrote the guidelines in 2010 and they sat in a draft form ever since. I no longer remember what I had in mind when I wrote "compiler" above. > > 3 Virtually anything else. :-) > > There are some very useful techniques that allow a single piece of > source to be expanded in multiple ways. I don't disagree. I don't want to discourage the use of the C preprocessor altogether, just to make sure its use is measured against the potential headaches. Dave -- David Young dyo...@pobox.com Urbana, IL (217) 721-9981