Here are some examples of macros taken from actual working C code, in
this case the code of GNU Emacs, the text editor of choice for many C
programmers, and in fact the editor in which this edition of the book
was written.
Most of the macro examples below define various types of integer as
having certain sizes. It can be very useful when doing advanced C
programming to know whether a long integer, for instance, is 32 or 64
bits long on your system; if you select the wrong size, your code might
crash or might not even compile. In the case of Emacs, the maximum size
of certain variables (how many bits they contain) affects every aspect
of its operation, even determining how long an Emacs text file can be.
Each piece of code below is prefixed with the name of the file from
which the code is taken, and followed by a note on some interesting
features of the macros defined.
emacs/src/config.h
/* Note that lisp.h uses this in a preprocessor conditional, so it
would not work to use sizeof. That being so, we do all of them
without sizeof, for uniformity's sake. */
#ifndef BITS_PER_INT
#define BITS_PER_INT 32
#endif
#ifndef BITS_PER_LONG
#ifdef _LP64
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif
#endif
In the middle of this set of macros, from config.h, the Emacs
programmer used the characters /* and */ to create an
ordinary C comment. C comments can be interspersed with macros freely.
The macro BITS_PER_INT is defined here to be 32 (but only if it
is not already defined, thanks to the #ifndef directive). The
Emacs code will then treat integers as having 32 bits. (See Integer variables.)
The second chunk of macro code in this example checks to see whether
BITS_PER_LONG is defined. If it is not, but _LP64 is
defined, it defines BITS_PER_LONG to be 64, so that all long
integers will be treated as having 64 bits. (_LP64 is a GCC
macro that is defined on 64-bit systems. It stands for "longs and
pointers are 64 bits".) If _LP64 is not present, the
code assumes it is on a 32-bit system and defines BITS_PER_LONG
to be 32.
emacs/src/lisp.h
/* These are default choices for the types to use. */
#ifdef _LP64
#ifndef EMACS_INT
#define EMACS_INT long
#define BITS_PER_EMACS_INT BITS_PER_LONG
#endif
#ifndef EMACS_UINT
#define EMACS_UINT unsigned long
#endif
#else /* not _LP64 */
#ifndef EMACS_INT
#define EMACS_INT int
#define BITS_PER_EMACS_INT BITS_PER_INT
#endif
#ifndef EMACS_UINT
#define EMACS_UINT unsigned int
#endif
#endif
This set of macros, from lisp.h, again checks to see
whether _LP64 is defined. If it is, it defines EMACS_INT
as long (if it is not already defined), and
BITS_PER_EMACS_INT to be the same as BITS_PER_LONG, which
was defined in config.h, above. It then defines
EMACS_UINT to be an unsigned long, if it is not already
defined.
If _LP64 is not defined, it is assumed we are on a 32-bit
system. EMACS_INT is defined to be an int if it is not
already defined, and EMACS_UINT is defined to be an
unsigned int if it is not already defined.
Again, note that the programmer has freely interspersed a comment with
the preprocessor code.
emacs/src/lisp.h
/* These values are overridden by the m- file on some machines. */
#ifndef VALBITS
#define VALBITS (BITS_PER_EMACS_INT - 4)
#endif
Here is another example from lisp.h. The macro VALBITS,
which defines another size of integer internal to Emacs, is defined as
four less than BITS_PER_EMACS_INT -- that is, 60 on 64-bit systems,
and 28 on 32-bit systems.
emacs/src/lisp.h
#ifndef XINT /* Some machines need to do this differently. */
#define XINT(a) ((EMACS_INT) (((a) << (BITS_PER_EMACS_INT - VALBITS)) \
>> (BITS_PER_EMACS_INT - VALBITS)))
#endif
The interesting feature of the XINT macro above is not only that
it is a function, but that it is broken across multiple lines with the
backslash character (\). The GCC preprocessor simply deletes the
backslash, deletes the preceding whitespace from the next line, and
appends it where the backslash was. In this way, it is possible to
treat long, multi-line macros as though they are actually on a single
line. (See Advanced operators, for more information on the the
advanced operators << and >>.)