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:
The behavior is undefined if the right operand is ... greater than or equal to the length in bits of the promoted left operand.
This behavior is undefined.
Consider some reading about how shifting by too many bits is malformed and how to protect yourself from it: INT34-C. Do not shift a negative number of bits or more bits than exist in the operand
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With