I must be absolutely crazy here, but gcc 4.7.3
on my machine is giving the most absurd result. Here is the exact code that I'm testing:
#include <iostream> using namespace std; int main(){ unsigned int b = 100000; cout << (b>>b) << endl; b = b >> b; cout << b << endl; b >>= b; cout << b << endl; return 0; }
Now, any number that's right shifted by itself should result in 0 (n/(2^n) == 0
with integer divide, n>1
, and positive/unsigned), but somehow here is my output:
100000 100000 100000
Am I crazy? What could possibly be going on?
A Right Arithmetic Shift of one position moves each bit to the right by one. The least significant bit is discarded and the vacant MSB is filled with the value of the previous (now shifted one position to the right) MSB.
It is frequently stated that arithmetic right shifts are equivalent to division by a (positive, integral) power of the radix (e.g., a division by a power of 2 for binary numbers), and hence that division by a power of the radix can be optimized by implementing it as an arithmetic right shift.
In an arithmetic shift-left, it multiplies a signed binary number by 2 and In an arithmetic shift-right, it divides the number by 2. In this one position moves each bit to the left one by one. The empty least significant bit (LSB) is filled with zero and the most significant bit (MSB) is rejected.
Right Shifts For signed numbers, the sign bit is used to fill the vacated bit positions. In other words, if the number is positive, 0 is used, and if the number is negative, 1 is used. The result of a right-shift of a signed negative number is implementation-dependent.
In C++ as in C, shifts are limited to the size (in bits) of the value shifted. For instance, if unsigned int is 32 bits, then a shift of more than 31 is undefined.
In practice, a common result is that the 5 least-significant bits of the shift amount are used and the higher order bits are ignored; this is due to the compiler producing a machine instruction which does exactly that (eg SHR on x86).
In this case, the shift value is 100000
(decimal) which happens to be 11000011010100000
in binary - the lower 5 bits are zero. So, you're effectively getting a shift by 0. You shouldn't rely on this however; technically, what you're seeing is undefined behaviour.
References:
For C, N1570 section 6.5.7:
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
For C++, N3690 section 5.8 "[expr.shift]":
The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.
N1570 is a draft, nearly identical to the released ISO C11 standard; this clause has been pretty much the same since the 1989 ANSI C standard.
N3690 is a recent draft of the C++ standard; I'm not sure whether it's the best one to use, but again, this clause hasn't changed.
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