tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

KNF and the C preprocessor

What do people think about setting stricter guidelines for using the
C preprocessor than the guidelines from the past?  Example guidelines:

The C preprocessor MAY be used for

1 Lazy evaluation: unlike a function call's arguments, a macro's
  arguments are not evaluated before the macro is "called."  E.g., in
  the code below, the second and following arguments of M(a, b, c, d, e)
  are not evaluated unless p(a) is true:

        #define M(__x, ...)                     \
        do {                                    \
                if (p(__x))                     \
                        f(__x, __VA_ARGS__);    \
        } while (false)

        M(a, b, c, d, e);

2 Lexical manipulation: e.g., concatenating symbols, converting symbols
  to strings:

        #define PAIR(__x)       { #__x, __x }

        struct {
                const char *name;
                unsigned int value;
        } errno_name_to_value[] = {PAIR(EINVAL), PAIR(EEXIST), PAIR(ENOENT)};

3 Generic programming:

        #define __arraycount(__x)       (sizeof(__x) / sizeof(__x[0]))

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 C preprocessor MUST NOT be used for

1 In-line code: 'static inline' subroutines are virtually always better
  than macros.

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.

3 Virtually anything else. :-)


David Young    Urbana, IL    (217) 721-9981

Home | Main Index | Thread Index | Old Index