USDA ARS

Macros

As a general rule, source code should contain no embedded literal constants. The two principal exceptions to this are strings controlling formatted output (e.g., in printf calls), and small integers used in loop indices or relative subscripts. All other constants should be replaced by #define macros. Not only does this make the code vastly easier to modify, but if the macro names are carefully chosen, they can contribute significantly toward making the code self-documenting.

Constants whose values depend on the values of other constants should be so defined.

Example:

#define N_PIXEL_BITS    32                              /* wrong */
#define N_PIXEL_BITS    ( sizeof(pixel_t) * CHAR_BIT )  /* right */

Constants whose values cannot be changed (i.e. they exist as macros only for readability) should be appropriately commented.

Example:

#define FALSE           0       /* boolean F: MUST BE 0 */

Use of macros to extend or redefine the syntax of C, or to redefine C keywords, should be avoided. Someone who knows C should not have to learn some strange new dialect in order to understand your code.

Any macro replacement text containing operators should be fully parenthesized, including an outermost set of parentheses around the entire replacement text. Arguments in function macro replacement should also be parenthesized, in case they expand into expressions containing operators.

Function macros should in general not contain C keywords or blocks of statements; this hinders readability by concealing the logic of the program.

Although conditional compilation is primarily a portability tool, two applications are important in code maintenance. To temporarily disable a section of code, use the construct

#if 0
	/* code to be disabled */
#endif

instead of "/* ... */"; this avoids the problem of nested comments.

Some library functions contain, in the same source file, a main routine that can be conditionally compiled with the function to perform stand-alone tests. IPW uses the symbol TEST_MAIN to control such compilation.

Example:

int
func(void)
{
        /* code for func() */
}

#ifdef TEST_MAIN
main()
{
        /* code which tests func() */
}
#endif

This code should appear at the end of the source file.


IPW documentation / Last revised 20 May 2009 / IPW web site