MISRA C:2012 Dir 4.9
A function should be used in preference to a function-like macro where they are interchangeable
Description
Directive Definition
A function should be used in preference to a function-like macro where they are interchangeable1 .
Rationale
When feasible, use functions instead of macros. Functions perform argument type checking and evaluate their arguments only once, avoiding problems with potential multiple side effects.
Polyspace Implementation
Polyspace® reports a violation of this rule if a macro is used at least once in the code and the macro can be replaced by a function. Polyspace assumes a macro cannot be replaced by a function if any these conditions are true:
The macro defines a function or a creates a call to a function using concatenation. For example, the macro
MYFUNC
allows inline creation of new functions using the macro parametername
. Polyspace assumes thatMyFunc
cannot be replaced by a function and does not report a violation.The macro//Noncompliant #define DH(x) do { printf("using variable = %d\n", x);} while(0) //Compliant #define MYFUNC(name) void myFunc_##name(){printf("call to function\n");}
DH
does not define a function or create calls to a function. Polyspace assumes that this macro can be replaced by a function and reports a violation.The macro breaks control flow using the keywords
return
,goto
,label
. Use of the keywordbreak
, or the keywordcontinue
outside aswitch
block or a loop also indicates that a macro cannot be replaced by a function. For example, the macroRETURN_NUM
returns a value. The macroCASES
contains thebreak
identifier outside aswitch
or a loop statement. Polyspace assumes that these macros cannot be replaced by a function.#define RETURN_NUM(x) do { \ an_uint32 += x; \ return 10; \ } while(0) #define CASES_(x) \ case 0: \ printf("0\n"); \ break; \ case 1: \ printf("1\n"); \ break; \ default: \ printf("default\n");
The macro declares at least one variable that is not used within the macro. For example, the macro
DECLARE_AND_INITIALIZE_VAR
declares and initializes three integers. Polyspace assumes that this macro cannot be replaced by a function.#define DECLARE_AND_INITIALIZE_VAR(x, y, z) \ int8_t x = 1; \ int8_t y = x + 1; \ int8_t z = y + 1;
The macro uses one of these symbols and keywords:
#
,__LINE__
,__FILE__
, and_Generic
.At least one of the macro parameters is used as a type in the body of the macro. For example, the macros
DECLARATION
andCONVERSION
each use one of their parameters as a type within its body. Polyspace assumes that these macros cannot be replaced by functions.#define DECLARATION(x, T) do { \ const T y = x; \ an_uint32 += y; \ } while(0) #define CONVERSION(x, T) ((T) (x))
At least one of the macro parameters is an operator or an expression. For example, the macro
OPERATION
takes an operator as an input. The macroSTATEMENT
takes an expression as an input. Polyspace assumes that these macros cannot be replaced by a function.#define OPERATION(x, y, op) ((x) op (y)) #define STATEMENT(x, action) \ if (!x) action
The macro is used for initializing a global or
static
variable. A function call is not permitted for this purpose.
Troubleshooting
If you expect a rule violation but do not see it, refer to Diagnose Why Coding Standard Violations Do Not Appear as Expected.
Examples
Check Information
Group: Code design |
Category: Advisory |
AGC Category: Advisory |
Version History
Introduced in R2014b1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.
The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:
MISRA C:2004
MISRA C:2012
MISRA C:2023
MISRA C++:2008
MISRA C++:2023
MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.