Macros are dangerous because their use resembles that of real functions, but they have different semantics. The C standard adds inline functions to the C programming language. Inline functions should be preferred over macros when they can be used interchangeably. Making a function an inline function suggests that calls to the function be as fast as possible by using, for example, an alternative to the usual function call mechanism, such as inline substitution. (See also PRE31-C. Avoid side-effects in arguments to unsafe macros, PRE01-C. Use parentheses within macros around parameter names, and PRE02-C. Macro replacement lists should be parenthesized.)
Inline substitution is not textual substitution, nor does it create a new function. For example, the expansion of a macro used within the body of the function uses the definition it had at the point the function body appeared, not where the function is called; and identifiers refer to the declarations in scope where the body occurs.
...
In this noncompliant code example, the macro CUBE()
has undefined behavior when passed an expression that contains side effects.
...
In this noncompliant code example, the programmer has written a macro called EXEC_BUMP()
to call a specified function and increment a global counter [Dewhurst 2002]. When the expansion of a macro is used within the body of a function, as in this example, identifiers refer to the declarations in scope where the body occurs. As a result, when the macro is called in the aFunc()
function, it inadvertently increments a local counter with the same name as the global variable. Note that this example also violates DCL01-C. Do not reuse variable names in subscopes.
Code Block | ||||
---|---|---|---|---|
| ||||
size_t count = 0; #define EXEC_BUMP(func) (func(), ++count) void g(void) { printf("Called g, count = %zu.\n", count); } void aFunc(void) { size_t count = 0; while (count++ < 10) { EXEC_BUMP(g); } } |
...
GNU C (and some other compilers) supported inline functions before they were added to the C standard and, as a result, have significantly different semantics. Richard Kettlewell provides a good explanation of differences between the C99 and GNU C rules [Kettlewell 2003].
Exceptions
PRE00-EX1: Macros can be used to implement local functions (repetitive blocks of code that have access to automatic variables from the enclosing scope) that cannot be achieved with inline functions.
...
calculates only one of the two expressions depending on the selector's value. See PRE05-C. Understand macro replacement when concatenating tokens or performing stringification for more information.
PRE00-EX3: Macros can be used to yield a compile-time constant. This is not always possible using inline functions, as shown by the following example:
...
An example of the use of function-like macros to create type-generic functions is shown in MEM02-C. Immediately cast the result of a memory allocation function call into a pointer to the allocated type.
Type-generic macros may also be used, for example, to swap two variables of any type, provided they are of the same type.
...
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
...
...
ISO/IEC TR 24772 | "NMP Pre-processor directives" |
MISRA | Rule 19.7 |
Bibliography
[Dewhurst 2002] | Gotcha #26, "#define Pseudofunctions" |
[FSF 2005] | Section 5.34, "An |
...
...
Macro" | |
ISO/IEC 9899:2011 | Section 6.7.4, "Function Specifiers" |
---|---|
[Kettlewell 2003] | |
[Summit 2005]AA. Bibliography#Summit 05 | Question 10.4 |
...