tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: KNF and the C preprocessor
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
dyoung%pobox.com@localhost Urbana, IL (217) 721-9981
Home |
Main Index |
Thread Index |
Old Index