2012-07-16 46 views
3

我發現當將uint64_t值右移64位或更多時,看起來是異常結果。我期望下面的代碼輸出值0,但它不 - 它輸出值>> 2 - 但只能用g ++。意外的結果從右移g ++

#include <iostream> 
#include <cstdint> 
using namespace std; 
int main(void) 
{ 
    uint64_t value = 0x5d4d629e80d5489UL; 
    int shift = 66; 
    cout << hex << (value >> shift) << endl; 
    return 0; 
} 

其中我編譯和運行:

$ g++ -std=c++0x mad.cpp 
$ ./a.out 
175358a7a035522 
$ uname -a 
Linux svr 3.2.0-26-generiC#41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux 
$ g++ --version 
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 

我得到另一個Linux機器相剋相同的行爲++(Debian的4.4.5-8)4.4.5。然而,當我用Visual Studio C++(Express Edition)編譯時,我得不到相同的行爲 - 我得到了我原本預期的結果 - 即0。可以安全地假設當x和y是序數時,C++中的x >> y應該產生0,並且y大於x中的位數。這是一個g ++的bug嗎?或者是Visual C++在這裏不符?我假設這不是/不應該是未定義的行爲?這可能是CPU專用?我知道,我總是可以明確地檢查每個超過8 * sizeof(value)的偏移 - 但是這引入了一個額外的分支,我希望在一些性能嚴重的代碼中避免這種分支。

這是一個已知問題嗎?如果是這樣的話,建議採取什麼策略以實現一致的跨平臺評估?

回答

9

從關於移位運算符C++標準:

的行爲是不確定如果將右操作數是 ...大於或等於所述長度在受促進的左操作數的位。

+0

這聽起來相當確鑿 - 「未定義的行爲」......我在猜測,我真的希望我的移位權被執行......即使它的位數多於數值的表示。 ..我需要使用顯式條件並指定0來避免未定義的行爲? – aSteve 2012-07-16 01:04:44

+0

@aSteve:差不多。 – 2012-07-16 01:10:57

0

一個原因是,它依賴於底層硬件,其不同實現的變化上。

在原來的8086上,這個轉換是按照每個位置一個時鐘滴答滴答的次數進行的。很快發現這導致保證的中斷響應時間爲糟糕的

因此,從286開始,硬件屏蔽了移位計數並僅使用較低位。當66變成2位置轉換時,這就是你所看到的。