uint64_t 値を 64 ビット以上右にシフトすると、異常な結果と思われるものを発見しました。次のコードが値 0 を出力することを期待していましたが、そうではなく、値>>2 を出力しますが、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
g++ (Debian 4.4.5-8) 4.4.5 を搭載した別の Linux ボックスでも同じ動作をします。ただし、これを Visual Studio C++ (Express Edition) でコンパイルすると、同じ動作が得られません。最初に期待していた結果、つまり 0 が得られます。
x と y が序数で、y が x のビット数よりも大きい場合、C++ の x>>y は 0 になると仮定しても安全かどうかを知りたいです。これは g++ のバグですか、それともここで準拠していないのは Visual C++ ですか? これは未定義の動作ではない/すべきではないと思いますか? これはCPU固有でしょうか?
8*sizeof(value) を超えるすべてのシフトをいつでも明示的にチェックできることを認識していますが、これにより、パフォーマンスが重要なコードで回避したい追加のブランチが導入されます。
これは既知の問題ですか? もしそうなら、一貫したクロスプラットフォーム評価を視野に入れた推奨戦略は何ですか?