Function-like macros
More complex than object-like macros, a function-like macro definition
declares the names of formal parameters within parentheses, separated
by commas. An empty formal parameter list is legal: such a macro can
be used to simulate a function that takes no arguments. C99 adds support
for function-like macros with a variable number of arguments. ILE
C++ supports function-like macros with a variable number of arguments,
as a language extension for compatibility with C
and
as part of C++0x.
- Function-like macro definition:
- An identifier followed by a parameter list in parentheses and
the replacement tokens. The parameters are imbedded in the replacement
code. White space cannot separate the identifier (which is the name
of the macro) and the left parenthesis of the parameter list. A comma
must separate each parameter.
For portability, you should not have more than 31 parameters for a macro. The parameter list may end with an ellipsis (…). In this case, the identifier
__VA_ARGS__may appear in the replacement list. - Function-like macro invocation:
- An
identifier followed by a comma-separated list of arguments in parentheses.
The number of arguments should match the number of parameters in the
macro definition, unless the parameter list in the definition ends
with an ellipsis. In this latter case, the number of arguments in
the invocation should exceed the number of parameters in the definition.
The excess are called trailing arguments. Once the preprocessor
identifies a function-like macro invocation, argument substitution
takes place. A parameter in the replacement code is replaced by the
corresponding argument. If trailing arguments are permitted by the
macro definition, they are merged with the intervening commas to replace
the identifier
__VA_ARGS__, as if they were a single argument. Any macro invocations contained in the argument itself are completely replaced before the argument replaces its corresponding parameter in the replacement code.A macro argument can be empty (consisting of zero preprocessing tokens). For example,#define SUM(a,b,c) a + b + c SUM(1,,3) /* No error message. 1 is substituted for a, 3 is substituted for c. */
__VA_ARGS__ in the replacement
list. The following example illustrates this: #define debug(…) fprintf(stderr, __VA_ARGS__)
debug("flag"); /* Becomes fprintf(stderr, "flag"); */- In character constants
- In string literals
- Surrounded by parentheses
SUM as having
two parameters a and b and the replacement
tokens (a + b): #define SUM(a,b) (a + b)c = SUM(x,y);
c = d * SUM(x,y);c = (x + y);
c = d * (x + y);#define SQR(c) ((c) * (c))c in
the definition in order to correctly evaluate an expression like:
y = SQR(a + b);y = ((a + b) * (a + b));y = (a + b * a + b);Arguments of the # and ## operators
are converted before replacement of parameters in a function-like
macro.
Once defined, a preprocessor identifier remains defined and in
scope independent of the scoping rules of the language. The scope
of a macro definition begins at the definition and does not end until
a corresponding #undef directive is encountered.
If there is no corresponding #undef directive, the
scope of the macro definition lasts until the end of the translation
unit.
#define x(a,b) x(a+1,b+1) + 4 x(20,10) x(20+1,10+1) + 4rather than trying to expand the macro x over
and over within itself. After the macro x is expanded,
it is a call to function x().
debug from
subsequent lines in the current file: #define debugYou can change the definition of a defined identifier or macro
with a second preprocessor #define directive only
if the second preprocessor #define directive is preceded
by a preprocessor #undef directive. The #undef directive
nullifies the first definition so that the same identifier can be
used in a redefinition.
Within the text of the program, the preprocessor does not scan character constants or string constants for macro invocations.
The following example program contains two macro definitions and a macro invocation that refers to both of the defined macros:
/**
** This example illustrates #define directives.
**/
#include <stdio.h>
#define SQR(s) ((s) * (s))
#define PRNT(a,b) \
printf("value 1 = %d\n", a); \
printf("value 2 = %d\n", b) ;
int main(void)
{
int x = 2;
int y = 3;
PRNT(SQR(x),y);
return(0);
}
After being interpreted by the preprocessor, this program is replaced by code equivalent to the following:
#include <stdio.h>
int main(void)
{
int x = 2;
int y = 3;
printf("value 1 = %d\n", ( (x) * (x) ) );
printf("value 2 = %d\n", y);
return(0);
}
value 1 = 4
value 2 = 3