I’ve discovered what looks to be anomalous results when shifting a uint64_t value right by 64-bits or more. I’d have expected the following code to output the value 0, but it doesn’t – it outputs value>>2 – but only with 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;
}
Which I compile and run:
$ 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
I get the same behaviour on another Linux box with g++ (Debian 4.4.5-8) 4.4.5. However, I don’t get the same behaviour when I compile this with Visual Studio C++ (Express Edition) – I get the result I’d originally expected – i.e. 0.
I’d like to know if it should be safe to assume that x>>y in C++ should yield 0 when x and y are ordinals and y is greater than the number of bits in x. Is this a g++ bug – or is it Visual C++ that’s non-conforming here? I’m assuming this isn’t/shouldn’t be undefined behaviour? Could this be CPU-specific?
I realise that I could always check explicitly for every shift exceeding 8*sizeof(value) – but that introduces an additional branch I’d hoped to avoid in some performance critical code.
Is this a known issue – and, if so, what is the recommended strategy with a view to consistent cross-platform evaluation?
From the C++ standard regarding shift operators: