2014-09-01 63 views
8

我在學習C++語言,我有類型轉換有些懷疑,你能解釋我這樣的表達會發生什麼:當我混合簽名和未簽名類型時會發生什麼?

unsigned int u = 10; 
int a = -42; 
std::cout << u - a << std::endl; 

在這裏,我知道結果將會是52歲,如果我申請的規則,當我們有兩個數學運算符。但我不知道會發生什麼時,編譯器將轉換爲無符號值創建一個臨時的無符號類型,會發生什麼後?現在的表達應該是10 -4294967254。

+0

你爲什麼不試試看? – dandan78 2014-09-01 15:45:19

+0

@ dandan78我想了解編譯器是如何工作的根本 – 2014-09-01 15:47:18

+2

@ dandan78上:有時這是天真的;特別是如果計算的任何方面是未定義的。 – Bathsheba 2014-09-01 15:48:00

回答

9

簡單來說,如果你混合類型相同的排名(的intlong intlong long int的順序),無符號的類型「勝」和計算是無符號類型中進行。結果是相同的無符號類型。

如果您混合使用不同級別的類型,則排名較高的類型爲「勝出」,如果它可以表示所有較低級別類型的值。計算在該類型中執行。結果是那種類型。最後,如果較高排名類型不能代表較低排名類型的所有值,則使用較高排名類型的無符號版本。結果是那種類型。

在你的情況下,你混合了相同排名的類型(intunsigned int),這意味着整個表達式在unsigned int類型中被評估。正如您正確指出的那樣,表達式現在是10 - 4294967254(對於32位int)。無符號類型遵循2^324294967296)作爲模的模運算規則。如果您仔細計算結果(可以用數學方式表示爲10 - 4294967254 + 4294967296),結果如預期的52

+0

對不起,我失去了自己,當表達變成:unsigned int temporary = 10 - 4294967254(好吧,我已經理解了這一點),但我不明白爲什麼表達式變成10 - 4294967254 + 4294967296(爲什麼你添加到模數算術?)。 – 2014-09-02 13:37:07

+0

@Piero Borrelli:計算'N'等於負值'V'的一種方法是根據需要多次添加'N'('V + N','V + 2N','V + 3N'等),直到你達到第一個非負值。在C++加法運算的情況下,數學上的負值結果只需要添加一次模值就可以得到正確的無符號結果。 – AnT 2014-09-02 14:12:48

+0

@Piero Borrelli:當然,這是純粹的算術規則。編譯器不需要做那樣的事情。它根本不用擔心。如果通過2的補碼來表示負值,則將該表示簡單地重新解釋爲無符號的值將立即提供正確的結果。 – AnT 2014-09-02 16:17:59

1

1)由於標準的促銷規則,signed類型a在減法之前被升級爲unsigned類型。這促進根據該規則(C++標準4.7/2)發生的情況:

如果目標類型是無符號的,所得到的值是至少 無符號整數全等到源整數(模2n,其中n是 的用於表示無符號類型的位數)。

代數a成爲一個非常大的正數並且肯定大於u

2)u - a是一個匿名臨時的,並且將是一個無符號的類型。 (您可以通過編寫auto t = u - a並在調試器中檢查t的類型來驗證。)在數學上,這將是一個負數,但是在隱式轉換爲無符號類型時,會調用類似於上面的環繞規則。

簡而言之,這兩種轉換操作具有相同和相反的效果,結果將爲52.實際上,編譯器可能會優化所有這些轉換。

-1

這裏是拆機代碼說:

其第一臺-42其補充,做副動作。所以結果是10 + 42 0x0000000000400835 <+8>: movl $0xa,-0xc(%rbp) 0x000000000040083c <+15>: movl $0xffffffd6,-0x8(%rbp) 0x0000000000400843 <+22>: mov -0x8(%rbp),%eax 0x0000000000400846 <+25>: mov -0xc(%rbp),%edx 0x0000000000400849 <+28>: sub %eax,%edx 0x000000000040084b <+30>: mov %edx,%eax

+1

在一般情況下,反彙編代碼不能作爲理解語言級語義的有意義的來源。代碼生成是單向函數。這是不可能的「追溯」。即通過查看生成的代碼來確定編譯器實際上試圖做什麼。 – AnT 2014-09-01 16:23:54

+0

感謝您的評論。 – 2014-09-02 02:03:44