」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 為什麼 C++ 中的右移位運算子 (`>>`) 在移位 32 位元時會產生意外結果?

為什麼 C++ 中的右移位運算子 (`>>`) 在移位 32 位元時會產生意外結果?

發佈於2024-11-01
瀏覽:586

C 中的

Why does the right shift operator (`>>`) 在移位 32 位元時會產生意外結果?
C 中的 >`) 在移位 32 位元時會產生意外結果? " />

右移運算子的意外行為(1 >> 32)

在程式設計領域,通常使用右移運算子(>>)執行按位元運算,特別是將整數除以2 的冪。 int a。 返回a>>b; } int bar(uint64_t a, int b) { 返回a>>b; } int main() { std::cout > 32: " > 32) > (int)32: " > (int)32)

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): 1 // Should be 0
欄(1, 32): 0
1>>32:0
(int)1 >> (int)32: 0

這些結果背後的基本原理在於 CPU 和編譯器的內部運作原理。
foo(1, 32): 1 // Should be 0
bar(1, 32): 0
1 >> 32: 0
(int)1 >> (int)32: 0

foo() 函數的行為

在foo()函數中,移位操作是在沒有強制轉換的情況下執行的,導致CPU執行邏輯右移。在許多架構上,邏輯右移被實作為 a >> (b % 32),有效地忽略 b 的高位。因此,foo(1, 32) 結果為 1 >> (32 % 32),其計算結果為 1 >> 0,產生 1。

為什麼轉換為 64 位元整數很重要?

在bar()函數中,提供了一個64位元無符號整數,確保結果保證為0,因為b(32)小於運算元中的位數(64 )。然而,當 b 更改為 64 時,結果變得不可預測,並且可能仍會產生 1。

編譯器最佳化

在 1 >> 32 且 (int )1 >> (int)32,編譯器在編譯時最佳化這些常數表達式。此標準指定了右移的未定義行為,其中計數為負數或大於或等於操作數的長度。由於 32 超出了操作數的長度,編譯器無法確定結果並輸出 0 作為安全後備。

CPU-Specific Behavior

右移的實現不同 CPU 的操作可能有所不同。在 x86/x86-64 架構上,邏輯右移其實是 a >> (b % 32 或 64),取決於模式。然而,在 ARM 處理器上,右移運算保證大於或等於 32 的移位為零。

結論

使用右移運算子時,這一點至關重要考慮潛在的未定義行為,特別是當移位計數超過操作數的長度時。轉換為更廣泛的整數類型(例如 64 位元整數)可以確保不同 CPU 和編譯器之間的結果一致。

最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3