Previous Page
Next Page

14.2. Defining and Using Macros

You can define macros in C using the preprocessor directive #define. This directive allows you to give a name to any text you want, such as a constant or a statement. Wherever the macro's name appears in the source code after its definition, the preprocessor replaces it with that text.

A common use of macros is to define a name for a numeric constant:

    #define ARRAY_SIZE 100
    double data[ARRAY_SIZE];

These two lines define the macro name ARRAY_SIZE for the number 100, and then use the macro in a definition of the array data. Writing macro names in all capitals is a widely used convention that helps to distinguish them from variable names. This simple example also illustrates how macros can make a C program more flexible. It's safe to assume that the length of an array like data will be used in several places in the programto control for loops that iterate through the elements of the array, for example. In each instance, use the macro name instead of a number. Then, if a program maintainer ever needs to modify the size of the array, it needs to be changed in only one place: in the #define directive.

In the third translation step, the preprocessor parses the source file as a sequence of preprocessor tokens and whitespace characters (see "The C Compiler's Translation Phases" in Chapter 1). If any token is a macro name, the preprocessor expands the macro; that is, it replaces the macro name with the text it has been defined to represent. Macro names that occur in string literals are not expanded, because a string literal is itself a single preprocessor token.

Preprocessor directives cannot be created by macro expansion. Even if a macro expansion results in a formally valid directive, the preprocessor doesn't execute it.

You can define macros with or without parameters.

14.2.1. Macros Without Parameters

A macro definition with no parameters has the form:

    #define macro_name replacement_text

Whitespace characters before and after replacement_text are not part of the replacement text. The replacement_text can also be empty. Some examples:

    #define TITLE  "*** Examples of Macros Without Parameters ***"
    #define BUFFER_SIZE  (4 * 512)
    #define RANDOM  (-1.0 + 2.0*(double)rand( ) / RAND_MAX)

The standard function rand( ) returns a pseudorandom integer in the interval [0, RAND_MAX]. The prototype of rand( ) and the definition of the macro RAND_MAX are contained in the standard header file stdlib.h.

The following statements illustrate one possible use of the preceding macros:

    #include <stdio.h>
    #include <stdlib.h>
    /* ... */
    // Display the title:
    puts( TITLE );

    // Set the stream fp to "fully buffered" mode, with a buffer of
    // BUFFER_SIZE bytes.
    // The macro _IOFBF is defined in stdio.h as 0.
    static char myBuffer[BUFFER_SIZE];
    setvbuf( fp, myBuffer, _IOFBF, BUFFER_SIZE );

    // Fill the array data with ARRAY_SIZE random numbers in the range
    // [-10.0, +10.0]:
    for ( int i = 0; i < ARRAY_SIZE; ++i )
      data[i] = 10.0 * RANDOM;

Replacing each macro with its replacement text, the preprocessor produces the following statements:

    puts( "*** Examples of Macros Without Parameters ***" );

    static char myBuffer[(4 * 512)];
    setvbuf( fp, myBuffer, 0, (4 * 512) );

    for ( int i = 0; i < 100; ++i )
      data[i] = 10.0 * (-1.0 + 2.0*(double)rand( ) / 2147483647);

In this example, the implementation-dependent value of the macro RAND_MAX is 2,147,483,647. With a different compiler, the value of RAND_MAX may be different.

If you write a macro containing an expression with operators, you should always enclose the expression in parentheses to avoid unexpected effects of operator precedence when you use the macro. For example, the outer parentheses in the macro RANDOM ensure that the expression 10.0 * RANDOM yields the desired result. Without them, macro replacement would produce this expression instead:

    10.0 * -1.0 + 2.0*(double)rand( ) / 2147483647

This expression yields a random number in the interval [-10.0, -8.0].

14.2.2. Macros with Parameters

You can also define macros with parameters. When the preprocessor expands such a macro, it incorporates arguments you specify for each use of the macro in the replacement text. Macros with parameters are often called function-like macros .

You can define a macro with parameters in either of the following ways:

    #define macro_name( [parameter_list] ) replacement_text
    #define macro_name( [parameter_list ,] ... )  replacement_text

The parameter_list is a comma-separated list of identifiers for the macro's parameters. When you use such a macro, the comma-separated argument list must contain as many arguments as there are parameters in the macro definition. (However, C99 allows you to use "empty arguments," as we will explain in a moment.) The ellipsis (...) stands for one or more additional arguments.

When defining a macro, you must make sure there are no whitespace characters between the macro name and the left parenthesis ((). If there is any space after the name, then the directive defines a macro without parameters whose replacement text begins with the left parenthesis.

The standard library usually includes macros, defined in stdio.h, to implement the well-known functions getchar( ) and putchar( ). Their expansion values can vary from one implementation to another, but in any case, their definitions are similar to the following:

    #define getchar( )   getc(stdin)
    #define putchar(x)  putc(x, stdout)

When you "call" a function-like macro, the preprocessor replaces each occurrence of a parameter in the replacement text with the corresponding argument. C99 allows you to leave blank the place of any argument in a macro call. In this case, the corresponding parameter is replaced with nothing; that is, it is deleted from the replacement text. However, this use of "empty arguments" is not yet supported by all compilers.

If an argument contains macros, these are ordinarily expanded before the argument is substituted into the replacement text. Arguments for parameters which are operands of the # or ## operators are treated specially. For details, see the subsequent subsections "The stringify operator" and "The token-pasting operator." Here are some examples of function-like macros and their expansions:

    #include <stdio.h>           // Contains the definition of putchar( ).
    #define DELIMITER ':'
    #define SUB(a,b)  (a-b)
    putchar( DELIMITER );
    putchar( str[i] );
    int var = SUB( ,10);

If putchar(x) is defined as putc(x, stdout), then the preprocessor expands the last three lines as follows:

    putc(':', stdout);
    putc(str[i], stdout);
    int var = (-10);

As the following example illustrates, you should generally enclose the parameters in parentheses wherever they occur in the replacement text. This ensures correct evaluation in case any argument is an expression:

    #define DISTANCE( x, y )  ((x)>=(y) ? (x)-(y) : (y)-(x))
    d = DISTANCE( a, b+0.5 );

This macro call expands to the following:

    d = ((a)>=(b+0.5) ? (a)-(b+0.5) : (b+0.5)-(a));

Without the parentheses around the parameters x and y, the expansion would contain the expression a-b+0.5 instead of (a)-(b+0.5). Variable numbers of arguments

The C99 standard lets you define macros with an ellipsis (...) at the end of the parameter list to represent optional arguments. You can then invoke such a macro with a variable number of arguments.

When you invoke a macro with optional arguments, the preprocessor groups all of the optional arguments, including the commas that separate them, into one argument. In the replacement text, the identifier _ _VA_ARGS_ _ represents this group of optional arguments. The identifier _ _VA_ARGS_ _ can be used only in the replacement text of a macro definition. _ _VA_ARGS_ _ behaves the same as any other macro parameter, except that it is replaced by all the remaining arguments in the argument list, rather than just one argument. Here is an example of a macro that takes a variable number of arguments:

    // Assume we have opened a log file to write with file pointer fp_log.
    #define printLog(...)  fprintf( fp_log, _  _VA_ARGS_  _ )
    // Using the printLog macro:
    printLog( "%s: intVar = %d\n", _  _func_  _, intVar );

The preprocessor replaces the macro call in the last line of this example with the following:

    fprintf( fp_log, "%s: intVar = %d\n", _  _func_  _, intVar );

The predefined identifier _ _func_ _, used in any function, represents a string containing the name of that function (see "Identifiers" in Chapter 1). Thus the macro call in this example writes the current function name and the contents of the variable intVar to the log file. The stringify operator

The unary operator # is commonly called the stringify operator (or sometimes the stringizing operator) because it converts a macro argument into a string. The operand of # must be a parameter in a macro replacement text. When a parameter name appears in the replacement text with a prefixed # character, the preprocessor places the corresponding argument in double quotation marks, forming a string literal. All characters in the argument value itself remain unchanged, with the following exceptions:

  • Any sequence of whitespace characters between tokens in the argument value is replaced with a single space character.

  • A backslash character (\) is prefixed to each double quotation mark character (") in the argument.

  • A backslash character is also prefixed to each existing backslash that occurs in a character constant or string literal in the argument, unless the existing backslash character introduces a universal character name (see "Universal Character Names" in Chapter 1).

The following example illustrates how you might use the # operator to make a single macro argument work both as a string and as an arithmetic expression in the replacement text:

    #define printDBL( exp ) printf( #exp " = %f ", exp )
    printDBL( 4 * atan(1.0));       // atan( ) is declared in math.h.

The macro call in the last line expands to this statement:

    printf( "4 * atan(1.0)" " = %f ", 4 * atan(1.0));

Because the compiler merges adjacent string literals, this code is equivalent to the following:

    printf( "4 * atan(1.0) = %f ", 4 * atan(1.0));

That statement would generate the following console output:

    4 * atan(1.0) = 3.141593

The invocation of the showArgs macro in the following example illustrates how the # operator modifies whitespace characters, double quotation marks, and backslashes in macro arguments:

    #define showArgs(...)  puts(#_  _VA_ARGS_  _)
    showArgs( one\n,        "2\n", three );

The preprocessor replaces this macro with the following text:

    puts("one\n, \"2\\n\", three");

This statement produces the following output:

    , "2\n", three The token-pasting operator

The operator ## is a binary operator, and can appear in the replacement text of any macro. It joins its left and right operands together into a single token, and for this reason is commonly called the token-pasting operator. If the resulting text also contains a macro name, the preprocessor performs macro replacement on it. Whitespace characters that occur before and after the ## operator are removed along with the operator itself.

Usually, at least one of the operands is a macro parameter. In this case, the argument value is first substituted for the parameter, but the macro expansion itself is postponed until after token-pasting. An example:

    #define TEXT_A "Hello, world!"
    #define msg(x) puts( TEXT_ ## x )

Regardless of whether the identifier A has been defined as a macro name, the preprocessor first substitutes the argument A for the parameter x, and then performs the token-pasting operation. The result of these two steps is the following line:

    puts( TEXT_A );

Now, because TEXT_A is a macro name, the subsequent macro replacement yields this statement:

    puts( "Hello, world!" );

If a macro parameter is an operand of the ## operator and a given macro invocation contains no argument for that parameter, then the preprocessor uses a placeholder to represent the empty string substituted for the parameter. The result of token pasting between such a placeholder and any token is that token. Token-pasting between two placeholders results in one placeholder. When all the token-pasting operations have been carried out, the preprocessor removes any remaining placeholders. Here is an example of a macro call with an empty argument:

    msg( );

This call expands to the following line:

    puts( TEXT_ );

If TEXT_ is not an identifier representing a string, the compiler will issue an error message.

The order of evaluation of the stringify and token-pasting operators # and ## is not specified. If the order matters, you can influence it by breaking a macro up into several macros.

14.2.3. Using Macros Within Macros

After argument substitution and execution of the # and ## operations, the preprocessor examines the resulting replacement text and expands any macros it contains. No macro can be expanded recursively, though; if the preprocessor encounters the name of any macro in the replacement text of the same macro, or in the replacement text of any other macro nested in it, that macro name is not expanded.

Similarly, even if expanding a macro yields a valid preprocessing directive, that directive is not executed. However, the preprocessor does process any _Pragma operators that occur in a completely expanded macro replacement (see "The _Pragma Operator," later in this chapter).

The following sample program prints a table of function values:

    // fn_tbl.c: Display values of a function in tabular form.
    //           This program uses nested macros.
    // -------------------------------------------------------------
    #include <stdio.h>
    #include <math.h>        // Prototypes of the cos( ) and exp( ) functions.

    #define PI          3.141593
    #define STEP        (PI/8)
    #define AMPLITUDE   1.0
    #define ATTENUATION 0.1              // Attenuation in wave propagation.
    #define DF(x)       exp(-ATTENUATION*(x))
    #define FUNC(x)    (DF(x) * AMPLITUDE * cos(x))  // Attenuated oscillation.
    // For the function display:
    #define STR(s)  #s
    #define XSTR(s) STR(s)            // Expand the macros in s, then stringify.

    int main( )
      double x = 0.0;

      printf( "\nFUNC(x) = %s\n", XSTR(FUNC(x)) );   // Print the function.

      printf("\n %10s %25s\n", "x", STR(y = FUNC(x)) );     // Table header.
      for ( ; x < 2*PI + STEP/2;  x += STEP )
        printf( "%15f %20f\n", x, FUNC(x) );

      return 0;

This example prints the following table:

    FUNC(x) = (exp(-0.1*(x)) * 1.0 * cos(x))

              x               y = FUNC(x)
           0.000000             1.000000
           0.392699             0.888302
           5.890487             0.512619
           6.283186             0.533488

14.2.4. Macro Scope and Redefinition

You cannot use a second #define directive to redefine an identifier that is currently defined as a macro, unless the new replacement text is identical to the existing macro definition. If the macro has parameters, the new parameter names must also be identical to the old ones.

To change the meaning of a macro, you must first cancel its current definition using the following directive:

    #undef macro_name

After that point, the identifier macro_name is available for use in a new macro definition. If the specified identifier is not the name of a macro, the preprocessor ignores the #undef directive.

The names of several functions in the standard library are also defined as macros. For these functions, you can use the #undef directive if you want to make sure your program calls one of those functions and not the macro of the same name. You don't need to specify a parameter list with the #undef directive, even when the macro you are undefining has parameters. An example:

    #include <ctype.h>
    #undef isdigit               // Remove any macro definition with this name.
    /* ... */
    if ( isdigit(c) )            // Call the function isdigit( ).
    /* ... */

The scope of a macro ends with the first #undef directive with its name, or if there is no #undef directive for that macro, then with the end of the translation unit in which it is defined.

Previous Page
Next Page