2012-04-01 24 views
13

なぜ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を使用しています。おかげさまで

+6

... d == c/1000です。これは本当の人生ですか? – outis

+2

@crushanator実際、aもdと等しくありません。あれ見た? –

+3

この例で1が2に等しくないのはなぜですか: 'int a = 1; int b = 2; '? –

答えて

5

intlongのサイズが同じプラットフォームを使用しているようです。 (私はlong場合は、あなたが見ている行動を見ていないでしょうunsigned intのすべての有効値を保持することができたという事実によって、これを推論しました。)

つまり表現a*z、両方azunsigned longに変換され、結果はunsigned longとなります。 (ISO/IEC 14882:2011、5 [expr]/9 ... "そうでなければ、両方のオペランドは、符号付き整数型のオペランドの型に対応する符号なし整数型に変換されるものとする")。この式をunsigned longからlongに変換した結果、a*zの正の値が符号付きlongで表現できないため、結果として実装定義の結果(負の値になります)が発生します。 c/1000では、はlongに変換され、longの除算が実行され(馬鹿を意図しない)、結果はlong(負である)となり、dに格納される。式a*z/10001000(タイプintの発現)において

unsigned longに変換され、分割は陽性の結果で得られた二unsigned longの間で行われます。この結果はlongと表され、値はlongに変換され、bに格納されると変更されません。

+0

これはMS Cコンパイラの場合の事実です。 – Inisheer

+0

符号付きオーバーフローは未定義の動作ですが、その方法です。 –

+1

@KerrekSB:はい、この例では署名付きオーバーフローはありません。 –