This operation is called "concatenation" or "token pasting". Showlist ( 1, "x", int ) // expands to puts("1, \"x\", int")Ī # operator between any two successive identifiers in the replacement-list runs parameter replacement on the two identifiers (which are not macro-expanded first) and then concatenates the result. When # appears before _VA_ARGS_, the entire expanded _VA_ARGS_ is enclosed in quotes: If the result of stringification is not a valid string literal, the behavior is undefined. This operation is called "stringification". All leading and trailing whitespace is removed, and any sequence of whitespace in the middle of the text (but not inside embedded string literals) is collapsed to a single space. In addition, the preprocessor adds backslashes to escape the quotes surrounding embedded string literals, if any, and doubles the backslashes within the string as necessary. In function-like macros, a # operator before an identifier in the replacement-list runs the identifier through parameter replacement and encloses the result in quotes, effectively creating a string literal. Note: if an argument of a function-like macro includes commas that are not protected by matched pairs of left and right parentheses (most commonly found in template argument lists, as in assert ( std:: is_same_v ) or BOOST_FOREACH ( std:: pair p, m )), the comma is interpreted as macro argument separator, causing a compilation failure due to argument count mismatch.Ī translation unit that includes a standard library header may not #define or #undef names declared in any standard library header.Ī translation unit that uses any part of the standard library may not #define or #undef names lexically identical to:Įxcept that likely and unlikely may be defined as function-like macros. G (a ) // replaced by f(0, a) #define SDEF(sname. G (a, b, c ) // replaced by f(0, a, b, c) The arguments (called variable arguments) can be accessed only with _VA_ARGS_ identifier, which is then replaced with arguments, supplied with identifier to be replaced.įor versions (3,4), replacement-list may contain the token sequence _VA_OPT_ ( content ), which is replaced by content if _VA_ARGS_ is non-empty, and expands to nothing otherwise. Version (4) of the #define directive defines a function-like macro with variable number of arguments, but no regular arguments. The additional arguments (called variable arguments) can be accessed using _VA_ARGS_ identifier, which is then replaced with arguments, supplied with the identifier to be replaced.
Version (3) of the #define directive defines a function-like macro with variable number of arguments. Version (2) of the #define directive defines a simple function-like macro. does not have parentheses after itself, it is not replaced at all. If the identifier is not in functional-notation, i.e. For versions (3,4), the number of arguments must not be less than the number of parameters ( not (since C++20) counting. The sequence is terminated by the matching ) token, skipping intervening matched pairs of left and right parentheses.įor version (2), the number of arguments must be the same as the number of parameters in macro definition. The syntax of a function-like macro invocation is similar to the syntax of a function call: each instance of the macro name followed by a ( as the next preprocessing token introduces the sequence of tokens that is replaced by the replacement-list. Version (1) of the #define directive behaves exactly like that.įunction-like macros replace each occurrence of defined identifier with replacement-list, additionally taking a number of arguments, which then replace corresponding occurrences of any of the parameters in the replacement-list.
Object-like macros replace every occurrence of defined identifier with replacement-list.
If the identifier is already defined as any type of macro, the program is ill-formed unless the definitions are identical. The #define directives define the identifier as macro, that is instruct the compiler to replace all successive occurrences of identifier with replacement-list, which can be optionally additionally processed.
#define identifier ( parameters ) replacement-list (optional) #define identifier replacement-list (optional)