2012-04-01 119 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 2012-04-01 13:31:56

+2

@crushanator其實a也不等於d。你看到了嗎? – 2012-04-01 13:34:02

+3

爲什麼在這個例子中1不等於2:'int a = 1; int b = 2;'? – 2012-04-01 13:34:08

回答

5

它看起來像你使用的平臺,其中intlong具有相同的大小。 (我的事實,如果long能夠容納所有的unsigned int你不會看到你所看到的行爲有效的值推斷出這一點。)

這意味着,在表達a*z,既az轉換爲unsigned long,結果的類型爲unsigned long。 (ISO/IEC 14882:2011,5 [expr]/9 ...「否則,兩個操作數都應轉換爲與帶符號整數類型的操作數類型相對應的無符號整數類型」)。將這個表達式從unsigned long轉換爲long,並且在您的情況下,這會導致實現定義的結果(該結果恰好爲負),因爲a*z的正值無法在簽名的long中表示。在c/1000,1000轉換爲longlong除法執行(無雙關意圖)導致long(這恰好是負數)並存儲到d

在表達式a*z/10001000int類型的表達式)轉化爲unsigned long和在兩個unsigned long之間執行的除法產生了陽性結果。該結果可表示爲long,並且該值在轉換爲long並存儲到b時未改變。

+0

這實際上就是MS C編譯器的情況。 – Inisheer 2012-04-01 13:48:32

+0

簽名溢出是未定義的行爲,但方式。 – 2012-04-01 13:49:02

+1

@KerrekSB:是的,但在這個例子中沒有簽名溢出。 – 2012-04-01 13:51:02