A macro in C/C++ is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls.
Object Like Macros
An object like macro is a simple identifier which will be replaced by a code fragment. To create macros use #define
directive. #define
is followed by the name of the macro and then the token sequence it should be an abbreviation for, which is variously referred to as the macro’s body, expansion or replacement list. For example,
#define BUFFER_SIZE 1024
Macro’s body ends at the end of the ‘#define’ line. To continue the definition of macro onto multiple lines, use backslash and newline. When the macro is expanded, however, it will all come out on one line. For example,
#define NUMBERS 1, \ 2, \ 3 int x[] = {NUMBERS}; // int x[] = { 1, 2, 3 };
When the preprocessor expands a macro name, the macro’s expansion replaces the macro invocation. Then the expansion is examined for more macros to expand. For example, TABLESIZE is expanded first to produce BUFSIZE, then that macro is expanded to produce the final result, 1024.
#define TABLESIZE BUFSIZE #define BUFSIZE 1024
Function Like Macros
Macros can also be defined like function whose use looks like a function call. These are called function-like macros. To define a function-like macro, use the #define
directive along with a pair of parentheses immediately after the macro name. For example,
#define lang_init() c_init()
Function-like macros can take arguments, just like true functions. To define a macro that uses arguments, you insert parameters between the pair of parentheses in the macro definition that make the macro function-like. To invoke a macro that takes arguments, you write the name of the macro followed by a list of actual arguments in parentheses, separated by commas.
When the macro is expanded, each use of a parameter in its body is replaced by the tokens of the corresponding argument. As an example, here is a macro that computes the minimum of two numeric values.
#define min(X, Y) ((X) < (Y) ? (X) : (Y)) x = min(a, b); // x = ((a) < (b) ? (a) : (b));
Function can also be passed using Macro. For example
#define MACROFOO(function, ...) (function)(__VA_ARGS__) /* expands to: (printf)("hello world%c", '!') */ MACROFOO(printf, "hello world%c", '!')
Concatenation
It is often useful to merge two tokens into one while expanding macros. This is called Token pasting or Token concatenation. The ##
preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either side of each ##
operator are combined into a single token, which then replaces the ##
and the two original tokens in the macro expansion. However, two tokens that don’t together form a valid token cannot be pasted together.
C preprocessor converts comments to whitespace before macros are even considered. Therefore, you cannot create a comment by concatenating ‘/’ and ‘*’. You can put as much whitespace between ‘##’ and its operands as you like, including comments, and you can put comments in arguments that will be concatenated.
struct command { char *name; void (*function) (void); }; struct command commands[] = { { "quit", quit_command }, { "help", help_command }, };
In above example, command name will be set twice. Once in the string constant (name
) and once in the function name. A macro which takes the name of a command as an argument can make this unnecessary. Function name can be created by concatenating the argument with ‘_command’. Here is how it is done:
#define COMMAND(NAME) { #NAME, NAME ## _command } struct command commands[] = { COMMAND (quit), COMMAND (help), };
Variadic Macros
A macro can be declared to accept a variable number of arguments much as a function can. The syntax for defining the macro is similar to that of a function. Here is an example:
#define eprintf(…) fprintf (stderr, __VA_ARGS__)
When the macro is invoked, all the tokens in its argument list after the last named argument (this macro has none), including any commas, become the variable argument. This sequence of tokens replaces the identifier __VA_ARGS__ in the macro body wherever it appears. Thus, we have this expansion:
eprintf ("%s:%d: ", input_file, lineno); // fprintf (stderr, "%s:%d: ", input_file, lineno)
You can have named arguments as well as variable arguments in a variadic macro. We could define eprintf like this, instead:
#define eprintf(format, …) fprintf (stderr, format, __VA_ARGS__)
Undefining and Redefining Macros
If a macro ceases to be useful, it may be undefined with the #undef
directive. ‘#undef’ takes a single argument, the name of the macro to un-define. You use the bare macro name, even if the macro is function-like. It is an error if anything appears on the line after the macro name. It has no effect if the name is not a macro.
#define FOO 4 x = FOO; → x = 4; #undef FOO x = FOO; → x = FOO;
Once a macro has been undefined, that identifier may be redefined as a macro by a subsequent #define
directive. The new definition need not have any resemblance to the old definition.