爲什麼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
,1000
轉換爲long
和long
除法執行(無雙關意圖)導致long
(這恰好是負數)並存儲到d
。
在表達式a*z/1000
,1000
(int
類型的表達式)轉化爲unsigned long
和在兩個unsigned long
之間執行的除法產生了陽性結果。該結果可表示爲long
,並且該值在轉換爲long
並存儲到b
時未改變。
這實際上就是MS C編譯器的情況。 – Inisheer 2012-04-01 13:48:32
簽名溢出是未定義的行爲,但方式。 – 2012-04-01 13:49:02
@KerrekSB:是的,但在這個例子中沒有簽名溢出。 – 2012-04-01 13:51:02
...因爲d == c/1000。這是真實的生活嗎? – outis 2012-04-01 13:31:56
@crushanator其實a也不等於d。你看到了嗎? – 2012-04-01 13:34:02
爲什麼在這個例子中1不等於2:'int a = 1; int b = 2;'? – 2012-04-01 13:34:08