メインコンテンツ

マクロに複数のステートメントがあります

マクロがセミコロンで終了する複数のステートメントで構成されており、ステートメントは中かっこで囲まれている場合と囲まれていない場合がある

説明

この欠陥は、ステートメントが中かっこで囲まれているかどうかに関係なく、マクロにセミコロンで終了する複数のステートメントが含まれている場合に発生します。

リスク

if 条件やループなどの特定のコンテキストでのマクロ展開は、不明なプログラム ロジックにつながる可能性があります。

たとえば、次のマクロを考えてみましょう。

#define RESET(x,y) \
   x=0; \
   y=0;
次のような if ステートメントでは、
if(checkSomeCondition)
   RESET(x,y);
マクロが次のように展開されます。
if(checkSomething)
   x=0;
y=0;
これは、if ブロックで両方のステートメントが実行された場合に予期せぬ結果を招く可能性があります。

修正方法

マクロ定義で、複数のステートメントを do...while(0) ループでラップします。

たとえば、前述の例では、次の定義を使用します。

#define RESET(x,y) \
   do { \
     x=0; \
     y=0; \
   } while(0)
このマクロは、あらゆるコンテキストでの展開に適しています。while(0) は、ステートメントが 1 回しか実行されないようにします。

または、複数のステートメントを呼び出す関数形式マクロよりインライン関数を使用します。

正しい解決策にはループが必須であり、中かっこでステートメントをラップしただけでは問題は解決されないことに注意してください。マクロ展開は意図しないコードにつながる可能性があります。

すべて展開する

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

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

この例では、マクロ RESET が複数のステートメントで構成されているために不具合が発生します。

修正 – マクロの複数のステートメントを do-while ループでラップする

マクロのステートメントをマクロ定義内の do..while(0) ループでラップします。

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

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

結果情報

グループ: 適切な手法
言語: C | C++
既定値: オフ
コマンド ライン構文: MULTI_STMT_MACRO
影響度: Low

バージョン履歴

R2020a で導入