1. ホーム
  2. c

[解決済み] 符号なし整数の減算は定義された動作ですか?

2022-10-09 13:28:38

質問

結果が負になるとき、同じ型の別の整数から符号なし整数を引くことに問題があると信じているような人のコードに出会いました。そのため、このようなコードは、ほとんどのアーキテクチャで動作するとしても、不正確なものになります。

unsigned int To, Tf;

To = getcounter();
while (1) {
    Tf = getcounter();
    if ((Tf-To) >= TIME_LIMIT) {
        break;
    } 
}

これは、私が見つけた C 標準からの唯一漠然とした関連性のある引用です。

符号なしオペランドを含む計算がオーバーフローすることはありません。 なぜなら、結果の符号なし整数型によって表現できない結果は、その数だけ減少するからです。 型が表現できない結果は、結果の型が表現できる最大の値より1つ大きい数で減数されるからです。 で表現できない結果は、結果の型によって表現できる最大の値より 1 つ大きい数で減速されるからです。

私は、右のオペランドがより大きいとき、演算はモジュロ切り捨てられた数のコンテキストで意味を持つように調整されるという意味で、この引用を取ることができると思います。

すなわち

0x0000 - 0x0001 == 0x 1 0000 - 0x0001 == 0xFFFF

実装に依存した符号付きセマンティクスを使用するのとは対照的に

0x0000 - 0x0001 == (unsigned)(0 + -1) == (0xFFFF だけでなく 0xFFFE や 0x8001 も)

どの、どのような解釈が正しいのでしょうか?それは全く定義されていないのですか?

どのように解決するのですか?

unsigned型で負数を発生させる引き算の結果はよく定義されています。

  1. [中略)符号なしオペランドを含む計算がオーバーフローすることは決してありません。 なぜなら、結果の符号なし整数型によって表現できない結果は で表現できない結果は、結果の型が表現できる最大の値より1つ大きい数で減速されるからです。 というのも,結果として得られる符号なし整数型で表現できない結果は,結果として得られる型で表現できる最大の値より1つ大きい数だけ減少するからです。 (iso/iec 9899:1999 (e) §6.2.5/9).

ご覧のとおりです。 (unsigned)0 - (unsigned)1 は-1 modulo UINT_MAX+1、言い換えればUINT_MAXに等しいことがわかります。

符号なしオペランドを含む計算は決してオーバーフローしない"とあり、上限を超える場合にのみ適用されると思われるかもしれませんが、これは モチベーション この文の実際の結合部分に対する動機付けとして提示されます: "結果の符号なし整数型で表現できない結果は 結果として得られる符号なし整数型で表現できない結果は、結果として得られる型で表現できる最大の値より1大きい数で減数されます。 このフレーズは、型の上限のオーバーフローに制限されておらず、表現するには低すぎる値にも同様に適用されます。