首頁 >後端開發 >C++ >## 為什麼右移位運算子在大移位值時會表現出意外行為?

## 為什麼右移位運算子在大移位值時會表現出意外行為?

Barbara Streisand
Barbara Streisand原創
2024-10-26 06:29:30619瀏覽

## Why Does the Right Shift Operator Exhibit Unexpected Behavior with Large Shift Values?

右移運算子的有趣行為

右移運算子(>>) 在處理較大的右移值時表現出特殊的行為。考慮以下程序:

<code class="c++">#include <iostream>
#include <stdint.h>

int foo(int a, int b)
{
   return a >> b;
}

int bar(uint64_t a, int b)
{
   return a >> b;
}

int main()
{
    std::cout << "foo(1, 32): " << foo(1, 32) << std::endl;
    std::cout << "bar(1, 32): " << bar(1, 32) << std::endl;
    std::cout << "1 >> 32: " << (1 >> 32) << std::endl; //warning
    std::cout << "(int)1 >> (int)32: " << ((int)1 >> (int)32) << std::endl; //warning
}</code>

foo(1, 32) 的預期輸出將為 0,但令人驚訝的是,它會傳回 1。這可以歸因於以下原因:

邏輯移位與算術移位

在x86/x86-64 架構上,右移運算子實際上執行邏輯右移,這表示它會填滿空出的空間帶有0 的位,無論左操作數的符號為何。此行為類似於使用>>> b.

編譯器最佳化

在foo(1, 32) 的情況下,值32 被轉換為int,這實際上被截斷為32 位元。由於 int 可以容納的最大值是 231-1,因此右移本質上是一個 >>> (32 % 32),其計算結果為 0。

未定義的行為

相關的C 標準規定,對於計數大於的右移,「行為未定義」大於或等於提升的左操作數的寬度。在這種情況下,1>>都成立。 32、(int)1>> (int)32 的計數大於 32,導致不可預測的結果。

與 bar(1, 32) 的區別

函數 bar 採用 64 位元無符號整數,保證寬度大於 32。因此,bar 中的右移不受未定義行為的影響。

結論

的行為當處理大的移位值時,右移運算子變得不明確。在 x86/x86-64 架構上,執行邏輯右移,而在 ARM 上,可能會使用不同的實作。由於未定義的行為,在可移植程式碼中應避免計數大於或等於操作數寬度的右移結果。

以上是## 為什麼右移位運算子在大移位值時會表現出意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn