The shifting
operators are used to do an arithmetic shift to the bits of an integral numeric value, either to
the left or the right.
var number = 14; // ...01110 (14)
var left = number << 1; // ...11100 (28)
var right = number >> 1; // ...00111 (7)
Therefore, shifting an integral number by 0 is equivalent to doing nothing, since the bits do not move any positions to the left or the right.
On the other hand, shifting an integral number by a value greater than their count of bits minus one (n_bits-1
) is equivalent to
shifting by the value modulo the bit count of the number (value % n_bits
).
In the case of int
and uint
, which take 32 bits in the memory, the shift count is given by the five low-order bits of the
second operand, which can represent numbers from 0 to 31. This means that numbers having the same five low-order bits are treated the same by the
shift operators.
var one = 0b0_00001;
var thirtyThree = 0b1_00001; // Same five low-order bits, 33 % 32 = 1
var shifted1 = 42 << one; // Results in 84
var shifted2 = 42 << thirtyThree; // Results in 84
Note that integral number with a less than 32-bit quantity (e.g. short
, ushort
) are implicitly converted to
int
before the shifting operation and so the rule for int
/uint
applies.
If the first operand is a long
or ulong
(64-bit quantity), the shift count is given by the six low-order bits of the
second operand. That is, the actual shift count is 0 to 63 bits.
Exceptions
This rule doesn’t raise an issue when the shift by zero is obviously for cosmetic reasons:
- When the value shifted is a literal.
- When there is a similar shift at the same position on line before or after. E.g.:
bytes[loc+0] = (byte)(value >> 8);
bytes[loc+1] = (byte)(value >> 0);