Macros are dangerous because their use resembles that of real functions, but they have different semantics. The inline function-specifier was introduced to the C programming language in the C99 standard. 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.
Arguably, a decision to inline a function is a low-level optimization detail that the compiler should make without programmer input. The use of inline functions should be evaluated on the basis of (a) how well they are supported by targeted compilers, (b) what (if any) impact they have on the performance characteristics of your system, and (c) portability concerns. Static functions are often as good as inline functions and are supported in C.
Noncompliant Code Example
In this noncompliant code example, the macro
CUBE() has undefined behavior when passed an expression that contains side effects:
For this example, the initialization for
a expands to
which is undefined (see EXP30-C. Do not depend on the order of evaluation for side effects).
When the macro definition is replaced by an inline function, the side effect is executed only once before the function is called:
Noncompliant Code Example
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.
The result is that invoking
aFunc() (incorrectly) prints out the following line five times:
In this compliant solution, the
EXEC_BUMP() macro is replaced by the inline function
aFunc() now (correctly) prints the value of
count ranging from 0 to 9:
The use of the inline function binds the identifier
count to the global variable when the function body is compiled. The name cannot be re-bound to a different variable (with the same name) when the function is called.
Noncompliant Code Example
Unlike functions, the execution of macros can interleave. Consequently, two macros that are harmless in isolation can cause undefined behavior when combined in the same expression. In this example,
G() both increment the global variable
operations, which causes problems when the two macros are used together:
operations is both read and modified twice in the same expression, so it can receive the wrong value if, for example, the following ordering occurs:
This noncompliant code example also violates EXP30-C. Do not depend on the order of evaluation for side effects.
The execution of functions, including inline functions, cannot be interleaved, so problematic orderings are not possible:
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].
PRE00-C-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.
PRE00-C-EX2: Macros can be used for concatenating tokens or performing stringification. For example,
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-C-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:
In this example, the
ADD_M(3,4) macro invocation yields a constant expression, but the
add_f(3,4) function invocation does not.
PRE00-C-EX4: Macros can be used to implement type-generic functions that cannot be implemented in the C language without the aid of a mechanism such as C++ templates.
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.
PRE00-C-EX5: Macro parameters exhibit call-by-name semantics, whereas functions are call by value. Macros must be used in cases where call-by-name semantics are required.
Improper use of macros may result in undefined behavior.
|Axivion Bauhaus Suite|
|LDRA tool suite|
A function should be used in preference to a function-like macro
|Polyspace Bug Finder|
|CERT C: Rec. PRE00-C||Checks for use of function-like macro instead of function (rec. fully covered)|
|SonarQube C/C++ Plugin|
|SEI CERT C++ Coding Standard||VOID PRE00-CPP. Avoid defining macros|
|ISO/IEC TR 24772:2013||Pre-processor Directives [NMP]|
|MISRA C:2012||Directive 4.9 (advisory)|
|[Dewhurst 2002]||Gotcha #26, "|
|[FSF 2005]||Section 5.34, "An Inline Function Is as Fast as a Macro"|
|[Summit 2005]||Question 10.4|