Main Content

Macro with multiple statements

Macro consists of multiple semicolon-terminated statements, enclosed in braces or not

Since R2020a

Description

This defect occurs when a macro contains multiple semicolon-terminated statements, irrespective of whether the statements are enclosed in braces.

Risk

The macro expansion, in certain contexts such as an if condition or a loop, can lead to unintended program logic.

For instance, consider the macro:

#define RESET(x,y) \
   x=0; \
   y=0;
In an if statement such as:
if(checkSomeCondition)
   RESET(x,y);
the macro expands to:
if(checkSomething)
   x=0;
y=0;
which might be unexpected if you want both statements to be executed in an if block.

Fix

In a macro definition, wrap multiple statements in a do...while(0) loop.

For instance, in the preceding example, use the definition:

#define RESET(x,y) \
   do { \
     x=0; \
     y=0; \
   } while(0)
This macro is appropriate to expand in all contexts. The while(0) ensures that the statements are executed only once.

Alternatively, use inline functions in preference to function-like macros that involve multiple statements.

Note that the loop is required for the correct solution and wrapping the statements in braces alone does not fix the issue. The macro expansion can still lead to unintended code.

Examples

expand all

#define RESET(x,y) \
   x=0; \
   y=0;

void func(int *x, int *y, int resetFlag){
    if(resetFlag)
        RESET(x,y);    
}

In this example, the defect occurs because the macro RESET consists of multiple statements.

Correction – Wrap Multiple Statements of Macro in do-while Loop

Wrap the statements of the macro in a do..while(0) loop in the macro definition.

#define RESET(x,y) \
   do { \
     x=0; \
     y=0; \
   } while(0)

void func(int *x, int *y, int resetFlag){
    if(resetFlag)
        RESET(x,y);    
}

Result Information

Group: Good practice
Language: C | C++
Default: Off
Command-Line Syntax: MULTI_STMT_MACRO
Impact: Low

Version History

Introduced in R2020a