[英]Undefined behaviour of right shift (a >> b) when b is greater than the number of bits in a?
顯然,右移操作的行為:
a >> b
當b >= sizeof(a)*CHAR_BIT
時,在C和C ++中未定義(而在正常情況下,由於右移而從左側引入的“新位”等於零)。
當b >= sizeof(a)*CHAR_BIT
時,為什么這種未定義的行為比將結果設置為零更好?
我們可以從為什么語言設計師容忍未定義的行為中選擇未定義的行為來理解為什么語言會說:
這個答案來自C背后的兩個一般設計原則:
- 該語言不應對實現施加任何不必要的開銷。
- 在各種硬件上實現C應該盡可能簡單。
在這種特定情況下,當我們使用大於位寬的移位計數時會發生什么情況將取決於架構,例如我在這里的答案中解釋:
在某些平台上,移位計數將被屏蔽為5 bits
,例如在x86
架構上我們可以看到IA-32架構兼容性中的英特爾®64和IA-32架構軟件開發人員手冊部分SAL / SAR / SHL / SHR-Shift部分說:
8086不掩蓋班次計數。 但是,所有其他IA-32處理器(從Intel 286處理器開始)確實將移位計數屏蔽為5位,最大計數為31. [...]
因此,在某些平台上實現任意計數的轉移可能會很麻煩,因此最好不要使用不確定的行為。
為什么不指定未指明的行為
未指定的行為使實現者在翻譯程序時具有一定的自由度。 然而,這個范圍沒有擴展到未能翻譯程序,因為所有可能的行為都是“正確的”,因為它們在任何實現中都不會導致未定義的行為。
因此,一定存在案例或者仍然存在行為不正確並且會出現問題的情況。
舉例說明為什么這種未定義的行為比將結果設置為零更好。
通常,CPU具有執行轉換的單個指令。 如果需要該指令與上限進行比較,則需要更多電路並減慢移位。 相反,許多CPU只是使用轉換的最低有效位來確定轉移多少。
// Example - not specified behavior (assume 32-bit int)
y = 1 << 34;
// same as
y = 1 << 2;
第一台PC使用8/16位處理器,使用最少8位來確定移位,因此一旦移位計數大於`int width但小於256,它確實會以零移位。這個問題是每個班次花了1個時鍾。 因此,在最壞的情況下,簡單的移位命令可能需要255個時鍾周期才能執行。 當然,在16個滴答之后,只有0被移動。 這個長期最壞情況的指令是不可中斷的! 因此,使處理器的最壞情況中斷延遲遠遠比競爭對手差。 英特爾沒有再犯這個錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.