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 - MYFUNCallows inline creation of new functions using the macro parameter- name. Polyspace assumes that- MyFunccannot 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");}- DHdoes 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 keyword- break, or the keyword- continueoutside a- switchblock or a loop also indicates that a macro cannot be replaced by a function. For example, the macro- RETURN_NUMreturns a value. The macro- CASEScontains the- breakidentifier outside a- switchor 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_VARdeclares 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 - DECLARATIONand- CONVERSIONeach 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 - OPERATIONtakes an operator as an input. The macro- STATEMENTtakes 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 - staticvariable. 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.