整数型が混在した C++ 算術演算でオーバーフローが発生する
-
21-12-2019 - |
質問
VC++2010で、追加操作でオーバーフローを引き起こすさまざまなサイズのオペランドを混合していくつかのテストを実行しました。
int _tmain(int argc, _TCHAR* argv[])
{
__int8 a=127;
__int8 b=1;
__int16 c=b+a;
__int8 d=b+a;
printf("c=%d,d=%d\n",c,d);
return 0;
}
//result is: c=128, d=-128
なぜ c==128 なのかわかりません。私の理解では、両方の加算において、b+a は依然として 2 の符号付き加算とみなされます。 8ビット 変数。したがって、結果はオーバーフローです。-128。 その後, 、最初の代入操作で結果は 16 ビット signed int にプロモートされ、 c は依然として 16 ビット -128 値を取得するはずです。私の理解は正しいでしょうか?C++ 標準は少し読みにくいです。第 4 章では整数昇格について話しているようですが、この特定の例に関連するものは見つかりません。
解決
私の理解では、どちらの加算でも、b+a は 2 つの符号付き 8 ビット変数の加算とみなされるということです。したがって、結果はオーバーフローです。-128。
いいえ、プロモーションは +
後ではなく評価されます。加算は両方の場合に発生します a
そして b
ポジティブです。両方の番号が次のように昇格されます。 int
s は加算の場合、2 つの正の数として加算され、16 ビット short に変換されます。プロセスのどの時点でもオーバーフローによって結果が負になることはなく、最終結果は 128 になります。
おそらく、これは理にかなっています:の行動 a
そして b
は数学の 2 つの数値に一致するため、言語実務者にとってより直感的になります。
他のヒント
それは不可欠なプロモーションです。
1 整数変換ランク(4.13)がintのランクより小さいBOOL、CHAR16_T、CHAR32_T、またはwchar_t以外の整数型の整数型の整数型の整数型は、INT型のPRVALUEに変換できます。intがソースタイプのすべての値を表すことができる場合。それ以外の場合、ソースPRValueはunsigned int型のPRVALUEに変換できます。[4.5]
この文で
__int16 c=b+a;
.
最初に、
char
とshort int
の値をすべてint
に自動的に上昇させます。このプロセスは積分プロモーションと呼ばれます。次に、すべてのオペランドが最大のオペランドの種類に変換され、これは型プロモーションと呼ばれます。[Herbert Schildt]
変数の値はb
とa
をint
に昇格してから、それらに適用されます。
2回補完整数表現では、符号付き値は最高ビットを設定することによって表されます。これにより、整数が署名されているかどうかにかかわらず、マシンは同じ手順を持つバイナリ整数を追加および減算できます。
a = 127 == 0x7F == 0b01111111
+ b = 1 == 0x01 == 0b00000001
-------------------------------
c = 128 == 0x80 == 0b10000000
d =-128 == 0x80 == 0b10000000
.
変数c
とd
は異なるタイプを持つことができますが、異なるタイプの整数は単なる2値値の解釈だけです。上記を見ることができるように、バイナリ値は8ビットで合っています。標準は、のサイズにゼロまたは符号拡張(昇格)するために数学的表現の条件を必要とするので、任意の数学が行われず、オペランドは符号拡張されず、その結果オペランドがどのタイプであっても常に0b10000000
です。
要約すると、結果の違いは、16ビット整数に、符号ビットが0b1000000000000000
(a+b
が持たない)、および8ビット整数に、符号ビットは0b10000000
であることです。 。