右移運算子的有趣行為
右移運算子(>>) 在處理較大的右移值時表現出特殊的行為。考慮以下程序:
#include
#include
int foo(int a, int b)
{
return a >> b;
}
int bar(uint64_t a, int b)
{
return a >> b;
}
int main()
{
std::cout > 32: " > 32) > (int)32: " > (int)32) foo(1, 32) 的預期輸出將為 0,但令人驚訝的是,它會傳回 1。這可以歸因於以下內容:
邏輯移位與算術運算Shift
在x86/x86-64 架構上,右移運算子實際上執行邏輯右移,這表示它用0 填滿空出的位,而不管左運算元的符號。此行為類似於使用>>> b.
編譯器優化
在foo(1, 32) 的情況下,值32 轉換為int,實際上被截斷為32 位元。由於 int 可以容納的最大值為 231-1,因此右移本質上是 >>> (32 % 32),其計算結果為 0。
Undefined行為
相關的 C 標準規定,對於計數大於或等於提升的左操作數寬度的右移,「行為未定義」。在這種情況下,1 >> 32 和 (int)1 >> (int)32 的計數都大於 32,導致不可預測的結果。
與 bar(1, 32)[ 的差異&&&&]
函數bar採用64位元無符號整數,保證其寬度大於32。因此,bar中的右移不受未定義行為的影響。 結論
處理大移位值時,右移運算子的行為變得不明確。在 x86/x86-64 架構上,執行邏輯右移,而在 ARM 上,可能會使用不同的實作。由於未定義的行為,在可移植程式碼中應避免計數大於或等於操作數寬度的右移結果。
免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。
Copyright© 2022 湘ICP备2022001581号-3