メインコンテンツ

整数定数のオーバーフロー

整数データ型の範囲外にある定数

説明

この欠陥は、次の場合に発生します。

  • コンパイル時の定数が、その値を格納できないデータ型の符号付き整数変数に代入されている。

    代入による定数オーバーフローを参照してください。

  • enum の潜在型に格納できない enum 値が使用されている (かつ、潜在型が符号付きである)。ほとんどの C コンパイラでは、既定で潜在型は signed int です (C 標準に基づく)。

    enum 値による定数オーバーフローを参照してください。

  • オーバーフローを発生させる 2 つの整数定数 (つまり、演算で使用されているデータ型の許容範囲外の値) を含む二項演算が実行されている。整数定数を使用する二項演算では signed int データ型が使用されます (ただし、uL などの修飾子を使用する場合は、その限りではありません)。

    二項演算による定数オーバーフローを参照してください。

n ビット符号付き整数は、範囲 [-2n-1, 2n-1-1] 内の値を保持します。たとえば、c は 8 ビットの符号付き char 型の変数であるため、値 255 を保持できません。

signed char c = 255;

この欠陥チェッカーは、次のオプションに依存します。

この欠陥は、次の状況では発生しません。

  • const 変数から新しい定数を作成する (特定のコンパイラのみ)。

    コンパイラによって、コンパイル時定数の定義方法は異なります。次のコードに含まれる c+1 は、GCC コンパイラではコンパイル時定数と見なされますが、標準 C コンパイラではそのように見なされません。

    const int16_t c = 32767;
    int16_t y = c + 1;
    y でのこのチェックの違反が検出されるかどうかは、コンパイラによって異なります。

  • ビット NOT 演算。

    Polyspace® では、ビット NOT 演算の実行時にこの違反が報告されません。

リスク

定数のオーバーフローの既定の動作は、コンパイルやプラットフォームによって異なる場合があります。定数のオーバーフローを維持するとコードの移植性が低くなる可能性があります。

コンパイラでオーバーフローした定数が警告を伴ってラップ アラウンドされる場合でも、ラップ アラウンドの動作は意図されたものではなく、予期しない結果を引き起こす可能性があります。

修正方法

定数値が意図したものかどうかをチェックします。値が正しい場合は、より大きい可能性のある別のデータ型をその変数に使用します。

すべて展開する

#define MAX_UNSIGNED_CHAR 255 
#define MAX_SIGNED_CHAR 127

void main() {
    char c1 = MAX_UNSIGNED_CHAR;
    char c2 = MAX_SIGNED_CHAR+1;
}

この例では、1 つ以上のマクロを使用するとオーバーフローが起こるため、マクロに欠陥が表示されます。この結果を再現するには、[ターゲット プロセッサ タイプ] (-target) を使用します。ここで、既定では char が符号付きになっています。

修正 — 別のデータ型を使用

1 つの修正方法として、オーバーフローする変数に別のデータ型を使用します。

#define MAX_UNSIGNED_CHAR 255 
#define MAX_SIGNED_CHAR 127

void main() {
    unsigned char c1 = MAX_UNSIGNED_CHAR;
    unsigned char c2 = MAX_SIGNED_CHAR+1;
}
enum {
  a=0x7fffffff,
  b,
  c=0xffffffff
} MyEnumA;

この例では、enum の潜在型は int です。int 型では、範囲 [-231, 231-1] の値を格納できます。ただし、列挙の値 b は 0x80000000 または 231 (前の a 値に 1 を足した値) です。この値は int の許容範囲外です。

c の値 (0xffffffff または 232-1) はさらに大きく、これもオーバーフローを発生させます。

この欠陥を確認するには、次のようにします。

const unsigned int K_ATM_Label_Ram_init_value [] = {
     0x06 | ( 3 << 29) ,
     0x80 | ( 9 << 29) ,
     ( 2 << 31 )         ,
};

この例では、シフト演算のうちの 2 つの結果が、signed int データ型では格納できない値になります。signed int データ型では、範囲 [-231, 231-1] の値を格納できます。以下の演算を考えます。

  • 9 << 29 の結果の値は 232+536870912 になります。

  • 2 << 31 の結果の値は 232 になります。

結果が変数 unsigned int に代入されるとしても、オーバーフローの検出では二項演算の潜在型、つまり signed int が使用されることに注意してください。

結果情報

グループ: 数値
言語: C | C++
既定値: オフ
コマンド ライン構文: INT_CONSTANT_OVFL
影響度: Medium

バージョン履歴

R2018b で導入