[英]Bitwise shift operators on signed types
我試圖理解有符號運算符在有符號和無符號類型上的行為。 根據ISO / IEC文件,以下是我的理解。
E1 << E2
的結果是E1左移E2位位置
左移帳戶中騰出的位將由零填充。
E1作為有符號非負數: E1 << E2
將導致E1乘以E2的2次冪,如果該值可由結果類型表示。
Q1:簽署否定書怎么樣?
Q2:在下面的上下文中,我無法理解“減少模數”的含義。 “如果E1具有無符號類型,則結果的值為E1×2E2,比結果類型中可表示的最大值減少一個模數” 。
E1 >> E2
的結果是E1右移E2位的位置。
E1為有符號非負/無符號 :結果的值是E1 / 2E2的商的整數部分
問題3:對於有符號的負整數,我看到,有些書定義了空位將填充1
詳細說明使用右移運算符對帶符號的負int。
Q1:左移位運算符對有符號整數類型的負值的行為是未定義的,當結果E1 * 2^E2
在類型中無法表示時,有符號整數類型的正值的行為也是如此。
標准(n1570草案)第6.5.7節第4和第5段明確提到了這一點:
4
E1 << E2
的結果是E1
左移E2
位位置; 騰出的位用零填充。 如果E1
具有無符號類型,則結果的值為E1 × 2^E2
,比結果類型中可表示的最大值減少一個模數。 如果E1
具有有符號類型和非負值, 並且在結果類型中可以表示E1 × 2^E2
,那么這就是結果值; 否則,行為未定義。
Q2:以無符號整數類型中可表示的最大值為模的減少模數意味着簡單地丟棄在左側移出的位。
數學上,如果無符號的類型的最大值是2^n - 1
(它是那種形式的總是),移位的結果E1
向左E2
位為值V
的范圍為0至2^n - 1
這樣的區別
(E1 * 2^E2 - V)
可以被2^n
整除,也就是說,它是將E1 * 2^E2
除以2^n
時得到的余數。
問題3:在移位有符號整數類型的負值時的行為是實現定義的。 最常見的行為(至少在兩個補碼機器上)是算術移位,也就是說,結果是向下舍入(朝向負無窮大)。
5
E1 >> E2
的結果是E1
右移E2
位的位置。 如果E1
具有無符號類型或者E1
具有有符號類型和非負值,則結果的值是E1 / 2^E2
的商的整數部分。 如果E1
具有帶符號類型和負值,則結果值是實現定義的。
回復:Q1
如果E1為負數,則行為未定義。
回復:Q2
無符號算術是“循環”的,也就是說,它是環繞的,因此UINT_MAX + 1
再次為0
。 就好像每個計算都是以模UINT_MAX + 1完成的。 考慮它的另一種方法是簡單地刪除左邊不適合的多余位。
回復:Q3
如果E1為負數,則結果為實現定義。 也就是說,它取決於您的機器/編譯器/選項,但必須在某處記錄(“定義”)行為,通常是編譯器手冊。 兩種流行的選擇是用左(1算術移位)或0(邏輯移位)填充左邊的輸入位。
如果你真的想了解按位移位運算符。 看看這些簡單的規則:
1)在左移,E1 << E2,右側的所有空位都將用零填充,如果數字是有符號或無符號無關緊要,則總是將零移入。
2)在左移,E1 >> E2,左側的所有空位,如果數為正,則為0;如果數為負,則為1。請記住,無符號數從不為負數。 一些實現也可能在某些機器上用0填充,即使數字是負數,所以永遠不要依賴於此。
所有其他場景可以通過這兩個簡單的規則來解釋。 現在,如果您想知道移位后結果的值,只需寫入數字的位表示並在紙上手動移位,並使用這兩個規則在空位處輸入位。 然后你就能更好地理解位移的工作原理。
For example lets take int i = 7;
i<<2
now i = 0000 0000 0000 0000 0000 0000 0000 0111
perform two left shits according to rule 1 would be:
0000 0000 0000 0000 0000 0000 0001 1100
它將給出28的值(E1 * 2E2 = 7 * 2 * 2 = 28),這與位模式表示的相同。
現在讓我解釋“減少模數”的事情,如果你移動一個大數字,比左邊的位將丟失,“減少模數”補償它,所以如果你的結果值如果大於最大值數據類型可以保持,左邊的位將丟失,然后:result =(E1 * 2 * E2)%(maximumValue + 1)。
對於其他各種情況,請記住以上規則,你很好:)
Q2:“降值模數X”在數學中表示“值mod X”,可以在C中寫為“value%X”。這部分只是解釋整數溢出是如何工作的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.