2016-01-29 18 views
2

今天通過一個bug的工作,我們意識到我們被隱式類型轉換。C++編譯器在這些隱式類型轉換的情況下會做什麼?

int64_t result = intA * intB;

在INTA和INTB均爲正int的情況下,它們可以在值> 2^31溢出。

我希望類似的問題,用下面的代碼:

int64_t result = (intA * intB) - int64A

但似乎在實踐中,如果我們沒有對intA * intB結果溢出。

是嗎?如果是這樣,爲什麼?我通讀了C++的一些隱式類型轉換規則,試圖瞭解它是否可能是因爲int64A操作數是64位,但找不到任何確鑿的結果。

+0

'(intA * intB)'總是以'int'精度執行。如果有一些輸出代碼不理解,請發佈[MCVE](http://stackoverflow.com/help/mcve)以及預期輸出和實際輸出。請注意,有符號整數溢出可能會導致*未定義行爲*,在這種情況下可能會發生任何輸出。 –

+1

您的編譯器可能會將這些值乘以64位寄存器,因此似乎可行,但不能保證該行爲。 – paddy

+1

如果溢出,則爲UB。一個可能的UB(在無限多的可能性中)是「表現得好像操作數被轉換爲'int64_t'」。 –

回答

1

我在這裏假設32位int

C++使添加用戶定義的轉換變得複雜,但讓我們假設用戶定義的轉換沒有在這裏考慮。

有關整數大多數算術運算(例如,不移位),你會得到如下的轉換(這是從內存...):

  • 每個操作數轉換爲int如果是窄而不是int,其類型的所有值都可以由int表示。

  • 如果每個操作數比unsigned窄,則轉換爲unsigned

  • 然後,如果其中一個類型更寬,則每個操作數都會轉換爲更寬類型的兩個操作數類型。

  • 如果它們寬度相同,但是一個是無符號的,那麼選擇無符號類型。

前兩個步驟被稱爲「整數提升」,後兩個步驟是「常規算術轉換」的一部分。

所以,如果你想要做的64位乘法,

int x, y; 
// Always done with int 
int r = x * y; // 32-bit 
// These are always done with int64_t 
int64_t r = (int64_t)x * y; 
int64_t r = x * (int64_t)y; 
int64_t r = (int64_t)x * (int64_t)y; 
// This is a 32-bit multiplication, you probably don't want this... 
// The RESULT is converted to 64 bit 
int64_t r = x * y; // 32-bit 
// Same thing... 
int64_t r = (int64_t)(x * y); // 32-bit 

減法恰好相乘的結果,因此,如果相乘結果是64位的,則減法將有64位完成。

不過:只要你用溢出整數運算,結果是不確定的!這意味着如果x * y溢出,編譯器可以執行任何想要的操作。也許它會給你帶來64位的結果。也許它崩潰了。也許它格式化你的硬盤。也許事情在你的程序中表現得很奇怪。

在實踐中,這是「有限的未定義的行爲」,所以它可能只會導致你撓頭而詛咒,而不是徹底崩潰你的程序。


: 「窄」 在技術上並不在標準中使用的術語。

相關問題