[previous_group] [previous] [up] [next] [next_group]

Macros with Arguments

We have previously seen simple macros, where the the macro value has been simple numbers.

But we can write macros that expand into any expression, again to make programs more readable. For example, if we wanted a macro to use to test if an integer is a multiple of 3, we could define a simple macro:

     #define MULTIPLE_OF_3   (((x) % 3) == 0)

Then, we can write a statement in a program:
     if( MULTIPLE_OF_3 )
     ...

which would expand to
     if( ((x % 3) == 0))
     ...

But the problem with this is that is only tests the variable, x. Suppose we had other variables we wanted to test?

We would like to parameterize the macro so we can tell it which variable to use instead of x. We can do that with a macro that has arguments:

     #define MULTIPLE_OF_3(x)   (((x) % 3) == 0)

Now we can use this single macro for testing any integer variable:
     if( MULTIPLE_OF_3(nickels) )
          if( MULTIPLE_OF_3(dimes) )
          ...

When the preprocessor expands these macros, a "double" substitution happens. For the case
     MULTIPLE_OF_3(nickels)

the argument given to the macro, nickels, is first substituted for x in all places it occurs in the macro definition, yeilding:
     #define MULTIPLE_OF_3(nickels) (((nickels) % 3) == 0)

as the "value" of the macro. This is then substituted for the macro in the if statement:
     if( (((nickels) % 3) == 0) )
          if( MULTIPLE_OF_3(dimes) )
          ...

Similarly for the second macro call,
     MULTIPLE_OF_3(dimes)

first substitutes dimes in the body of the macro:
     #define MULTIPLE_OF_3(dimes) (((dimes) % 3) == 0)

and the macro body then replaces the call in the statement:
     if( (((nickels) % 3) == 0) )
          if( (((dimes) % 3) == 0) )
          ...

and this is what the compiler sees after preprocessing.

So, back to our PICK macro. It has 2 arguments which are stubstituted the same way. In this case, we also have some simple macros in the picture. In guess.c we have the statement:

     hidden_number = PICK(START,STOP);

first the simple macros in guess.h get expanded to become:
     hidden_number = PICK(    1, 100);

Then, the definition of PICK:
     #define PICK(start,stop) (rand() % ((stop) - (start) + 1) + (start))

also in guess.h gets the arguments:
     #define PICK(    1, 100) (rand() % ((stop) - (start) + 1) + (start))

which are substituted in the body:
     #define PICK(    1, 100) (rand() % (( 100) - (    1) + 1) + (    1))

and then the result is substituted in the statement:
     hidden_number = (rand() % (( 100) - (    1) + 1) + (    1));

Notice the "excessive" parentheses in the macro definitions?

Why do you think that is?
[up] to Overview.

[next]