なぜd
はこの例ではb
と等しくないのですか?奇妙な計算結果
unsigned int z = 176400;
long a = -4;
long b = a*z/1000; //b=4294261
long c = a*z; // c=-705600
long d = c/1000; // d =-705
私はVisual Studio 2008、windows XP、core2duoを使用しています。おかげさまで
なぜd
はこの例ではb
と等しくないのですか?奇妙な計算結果
unsigned int z = 176400;
long a = -4;
long b = a*z/1000; //b=4294261
long c = a*z; // c=-705600
long d = c/1000; // d =-705
私はVisual Studio 2008、windows XP、core2duoを使用しています。おかげさまで
int
とlong
のサイズが同じプラットフォームを使用しているようです。 (私はlong
場合は、あなたが見ている行動を見ていないでしょうunsigned int
のすべての有効値を保持することができたという事実によって、これを推論しました。)
つまり表現a*z
、両方a
とz
でunsigned long
に変換され、結果はunsigned long
となります。 (ISO/IEC 14882:2011、5 [expr]/9 ... "そうでなければ、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されるものとする")。この式をunsigned long
からlong
に変換した結果、a*z
の正の値が符号付きlong
で表現できないため、結果として実装定義の結果(負の値になります)が発生します。 c/1000
では、はlong
に変換され、long
の除算が実行され(馬鹿を意図しない)、結果はlong
(負である)となり、d
に格納される。式a*z/1000
、1000
(タイプint
の発現)において
はunsigned long
に変換され、分割は陽性の結果で得られた二unsigned long
の間で行われます。この結果はlong
と表され、値はlong
に変換され、b
に格納されると変更されません。
これはMS Cコンパイラの場合の事実です。 – Inisheer
符号付きオーバーフローは未定義の動作ですが、その方法です。 –
@KerrekSB:はい、この例では署名付きオーバーフローはありません。 –
... d == c/1000です。これは本当の人生ですか? – outis
@crushanator実際、aもdと等しくありません。あれ見た? –
この例で1が2に等しくないのはなぜですか: 'int a = 1; int b = 2; '? –