Rules:
6.3.a. Parameterized macros shall not be used if a function can be written to accomplish the same behavior.
6.3.b. If parameterized macros are used for some reason, these rules apply:
i. Surround the entire macro body with parentheses.
ii. Surround each use of a parameter with parentheses.
iii. Use each parameter no more than once, to avoid unintended side effects.
iv. Never include a transfer of control (e.g., return keyword).
Example:
// Don’t do this ...
#define MAX(A, B) ((A) > (B) ? (A) : (B))
// ... when you can do this instead.
inline int max(int num1, int num2)
Reasoning: There are a lot of risks associated with the use of preprocessor defines, and many of them relate to the creation of parameterized macros. The extensive use of parentheses (as shown in the example) is important, but does not eliminate the unintended double increment possibility of a call such as MAX(i++, j++). Other risks of macro misuse include comparison of signed and unsigned data or any test of floating-point data. Making matters worse, macros are invisible at run-time and thus impossible to step into within the debugger.
Where performance is important, note that C99 added C++’s inline keyword.
Enforcement:
These rules shall be enforced during code reviews.