メインコンテンツ

式の二次的影響は無視されます

二次的影響のある式に対して実行される sizeof_Alignof、または _Generic

説明

この欠陥は、sizeof_Alignof、または _Generic 演算子が二次的影響のある式に対して実行された場合に発生します。評価されると、二次的影響のある式はその式内の 1 つ以上の変数を変更します。

たとえば、n+1 では n が変更されないため、欠陥チェッカーは sizeof(n+1) にフラグを設定しません。n++n を変更することを意図しているため、チェッカーは sizeof(n++) にはフラグを設定します。

このチェッカーは C++ の演算子 alignof と、その C 拡張 __alignof__ および __typeof__ にも適用されます。

リスク

_Alignof または _Generic 演算子の式は評価されません。sizeof 演算子の式は、sizeof(a[n++]) など、可変長配列のサイズを計算するためにそれが必要な場合に限り評価されます。

二次的影響のある式が評価されない場合、二次的影響による変数の変更は発生しません。その変更に依存している場合、予期しない結果になる可能性があります。

修正方法

別のステートメントで二次的影響のある式を評価してから、sizeof_Alignof、または _Generic 演算子でその結果を使用します。

たとえば、以下のようにはしません。

a = sizeof(n++);
次の 2 ステップで演算を実行します。
n++;
a = sizeof(n);

チェッカーは、関数呼び出しを二次的影響のある式と見なします。現在は関数に二次的影響がない場合でも、後の加算に対して二次的影響をもつ可能性があります。関数を sizeof 演算子の外部で呼び出すと、コードの保守が容易になります。

すべて展開する

#include <stdio.h>

void func(void) {
    unsigned int a = 1U;
    unsigned int b = (unsigned int)sizeof(++a);
    printf ("%u, %u\n", a, b);
}

この例では、a を変更することを目的とした ++a に対して sizeof を実行しています。式が評価されないため、変更は発生しません。printf ステートメントにより、a の値が 1 のままであることが示されます。

修正 — sizeof の外部でインクリメントを実行

1 つの修正方法として、最初にインクリメントを実行してから、その結果を sizeof 演算子に渡します。

#include <stdio.h>

void func(void) {
    unsigned int a = 1U;
    ++a;
    unsigned int b = (unsigned int)sizeof (a); 
    printf ("%u, %u\n", a, b);
}

結果情報

グループ: プログラミング
言語: C | C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: SIDE_EFFECT_IGNORED
影響度: Low

バージョン履歴

R2018a で導入