Macro Call as Macro Argument

Input ISO C

This problem is best explained with a small example. Consider the following:

# define  foo(unused)
# define  bar(x, y)      ((x) + (y))

foo (bar (1))

Is this legal? (Note that macro bar expects two arguments, but the "call" provides only one.)


Normally, this is not a problem. The number of macro arguments given in a macro invocation must agree with the number of arguments specified in the macro's definition ([ISO 6.8.3, 4th Paragraph]):

The number of arguments in an invocation of a function-like macro shall agree with the number of parameters in the macro definition, and ...

But of course this is not the whole story. The crucial point here is how and when macro substitution takes place. The standard says (all emphasis added):

[ISO 6.8.3, last paragraph]
The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. ...

[ISO 6.8.3.1]
After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless ..., is replaced by the corresponding argument after all macros therein have been expanded. Before being substituted, each argument's preprocessing tokens are completely macro replaced as if they formed the rest of the translation unit; no other preprocessing tokens are available.

What happens is therefore the following:

  1. We identify the whole macro invocation and find the preprocessing token sequence

    foo (bar (1))
  2. We see that this is an invocation of the function-like macro foo, so we try to identify its arguments and find that there is one:

    bar (1)
  3. We check the number of arguments of macro foo against its definition and find that they agree.

  4. We take a look at the replacement list to find out what we're supposed to do with the macro's argument.

  5. We find that the replacement list does not contain the argument, and so we can do the replacement directly, ignoring the argument.

  6. Then we continue by re-scanning the resulting replacement as defined in [ISO 6.8.3.4].

As you can see, there is no invocation of macro bar, and since the aforementioned paragraph [ISO 6.8.3, 4th Paragraph] explicitly states

The number of arguments in an invocation of a function-like macro...
(Emphasis added)

it does not apply in this case.

So, the answer is: yes, above source fragment is legal in C. However, if we'd written (instead of "foo (bar (1))")

bar (1)

the fragment would be wrong: then we would have an invocation of bar, and then the number of arguments must match.