Background
Function-like macros are an important part of the C preprocessor, introduced for quickly incorporating repetitive code snippets and simplifying debugging. They are used for small functions, inlining, or optimization.
Issue
Macros do not check types and do not provide full substitution beyond simple text replacement. Errors occur due to missing parentheses and substitution of expressions with side effects.
Solution
Enclose parameters and macro definitions in parentheses, avoid side effects in arguments, and use inline functions for more complex cases.
Code example:
#define MAX(a, b) ((a) > (b) ? (a) : (b)) int x = 5, y = 10; int z = MAX(x++, y++); // Dangerous call!
Key features:
Does a macro always fully replace code like a function?
No! A macro is just a text substitution before compilation; it can behave differently than a function if arguments are expressions with side effects.
Can any call (including with ++, --) be used as a macro parameter?
This is extremely dangerous. Side effects will occur multiple times if the parameter is used more than once in the macro.
Code example:
// This call will increase x or y more than by 1 MAX(x++, y++)
How to correctly include parentheses in macro declarations?
Enclose both parameters and the expression inside the macro in parentheses to avoid associativity errors when called within other expressions.
A company had a macro #define SQUARE(x) xx defined for many years, and it was used for expressions like SQUARE(a+1). Unexpected errors arose: the expression expanded as a+1a+1, which is different from (a+1)*(a+1).
Pros:
The macro SQUARE was written with full parentheses: #define SQUARE(x) ((x)*(x)). Its usage is standardized and documented.
Pros: