[英]Left-shift by (64 > shift > 32) bits on UINT64 in VS shifts only 32 bits
[英]Left shift an integer by 32 bits
在GCC下,以下代碼始終返回<<
if num1s == 0
的左操作數:
0xFFFFFFFFu << (32-num1s);
讀完后為什么沒有離開位移“<<”,32位整數在使用超過32次時按預期工作? ,以及David Heffernan引用的標准,似乎如果左操作數是無符號的 ,則它是一個已定義的操作。 只有當E1(左操作數)具有有符號類型和非負值時,才會導致未定義的行為。
任何人都可以解釋標准是否明確說明如果移位的數量大於類型包含的位數,那么它是未定義的行為嗎?
§5.8轉移運營商
結果的類型是提升的左操作數的類型。 如果右操作數為負數,或者大於或等於提升左操作數的位長度,則行為未定義。
E1 << E2
的值是E1
左移E2
位位置; 空位是零填充的。 如果E1
具有無符號類型,則結果的值為E1 × 2E2
,比結果類型中可表示的最大值減少一個模數。 否則,如果E1
具有有符號類型和非負值,並且在結果類型中可以表示E1×2E2
,那么這就是結果值; 否則,行為未定義。
CoryKramer已經回答了為什么它是標准的未定義行為。
我將嘗試在實際情況中證明它是如何工作的。 C ++編譯器通常將32位整數的<<
和>>
運算符實現為匯編程序指令而不檢查操作數范圍。 這意味着結果取決於移位指令的特定於處理器的實現。
例如,針對32位SHL / SHR / SAL / SAL指令的英特爾處理器規范說:
目標操作數可以是寄存器或存儲器位置。 計數操作數可以是立即值或寄存器CL。 計數被屏蔽為5位,這將計數范圍限制為0到31。
這意味着a << b
在Intel處理器上變為a << (b & 0x1f)
。 因此,移位32位意味着沒有移位。
但你不應該依賴這些信息! 編譯器還可以優化代碼並使用向量指令實現移位運算符。 在這種情況下,即使按處理器規范,也未指定行為。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.