2015-10-10 27 views
0

在GCC轉移的整數,下面的代碼總是返回<<如果num1s == 0的左操作數:留下的32位

0xFFFFFFFFu << (32-num1s); 

閱讀Why doesn't left bit-shift, "<<", for 32-bit integers work as expected when used more than 32 times?後,由大衛·赫弗南引用的標準,似乎如果左操作數是無符號,它是一個已定義的操作。只有當E1(左操作數)具有帶符號的類型和非負值時纔會導致未定義的行爲。

任何人都可以解釋,如果標準明確規定,如果移位量大於該類型包含的位數,它是未定義的行爲

+0

「如果右操作數爲負數,或者大於或等於升級的左操作數的位長度,則行爲未定義。」但嚴重的是,讓自己獲得一份標準副本,這些問題對你自己來說是微不足道的。 –

+0

爲什麼它會是一個未定義的行爲?它是非常明確的,操作會產生一個'0'。 – YePhIcK

+2

@YePhIcK純粹是因爲它被定義爲是未定義的。 –

回答

4

§5.8移位運算符

結果類型的是,促進了左操作數。 如果右操作數爲負數,或者大於或等於提升的左操作數的位長度,則行爲未定義。

E1 << E2的值是E1左移E2位位置;空位被零填充。如果E1具有無符號類型,則結果的值爲E1 × 2E2,比結果類型中可表示的最大值多一個模數。否則,如果E1具有帶符號的類型和非負值,並且E1×2E2可以在結果類型中表示,那麼這就是結果值;否則,行爲是不確定的。

+0

感謝來自標準的報價。某處是否有免費的C++標準? – Rich

+0

@Rich你可以在[這裏]獲取它(https://isocpp.org/std/the-standard)。最終確定的標準必須購買,但您可以在同一頁上免費獲得草稿(與最終版本相同的99%)。 – CoryKramer

1

CoryKramer回答了爲什麼它是標準的未定義行爲。

我會盡量擴展它在真實情況下的工作方式。 C++編譯器通常將32位整數作爲彙編指令執行<<>>運算符,而不檢查操作數範圍。這意味着結果取決於移位指令的處理器特定實現。

例如,對於32位SHL/SHR/SAL/SAL指令英特爾處理器規範說:

目標操作數可以是寄存器或內存位置。計數操作數可以是立即數或CL寄存器。計數 掩蔽以五個比特,這限制了計數範圍爲0到31。

這意味着a << b變得英特爾處理器a << (b & 0x1f)。所以移位32位意味着沒有移位。

但是你不應該依賴這些信息!編譯器還可以優化代碼並使用向量指令實現移位運算符。在這種情況下,即使通過處理器規格,行爲也是未指定的。

+0

很好的信息知道。謝謝! – Rich