/* I can not understand this operatore (c# reference) */
class MainClass1
{
static void Main()
{
int i = 1;
long lg = 1;
Console.WriteLine("0x{0:x}", i << 1);
Console.WriteLine("0x{0:x}", i << 33);
Console.WriteLine("0x{0:x}", lg << 33);
}
}
/*
Output:
0x2
0x2
0x200000000
*/
class MainClass2
{
static void Main()
{
int a = 1000;
a <<= 4;
Console.WriteLine(a);
}
}
/*
Output:
16000
*/
views:
626answers:
4<<
is the left-shift operator; this takes the binary representation of a value, and moves all the bits "n" places to the left (except for "mod", see "1"), back-filling with zeros.
>>
is the right-shift operator; this does nearly the opposite (moving to the right), except for signed values (i.e. those that can be negative) it back-fills with 1s for negative values, else zeros.
1:
The shift operator is essentially "mod" the width of the data. An int is 32 bits, so a left shift of 33 (in Int32) is exactly the same as a left shift of 1. You don't get all zeros. A long
is 64 bits, so a left-shift of 33 gives a different answer (original times 2^33).
2:
Each left shift (within the data width) is the same (for integers) as x2 - so <<4 is x2x2x2x2 = x16.
This is simple binary:
0000000001 = 1
<< goes to
0000000010 = 2
<< goes to
0000000100 = 4
<< goes to
0000001000 = 8
Just to expand on Marc's answer a little (Marc, feel free to include this in yours and I'll delete this answer) this is specified in section 7.8 of the spec:
The predefined shift operators are listed below.
Shift left:
- int operator <<(int x, int count);
- uint operator <<(uint x, int count);
- long operator <<(long x, int count);
- ulong operator <<(ulong x, int count);
The << operator shifts x left by a number of bits computed as described below.
The high-order bits outside the range of the result type of x are discarded, the remaining bits are shifted left, and the low-order empty bit positions are set to zero.
Shift right:
- int operator >>(int x, int count);
- uint operator >>(uint x, int count);
- long operator >>(long x, int count);
- ulong operator >>(ulong x, int count);
The >> operator shifts x right by a number of bits computed as described below.
When x is of type int or long, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero if x is non-negative and set to one if x is negative.
When x is of type uint or ulong, the low-order bits of x are discarded, the remaining bits are shifted right, and the high-order empty bit positions are set to zero.
For the predefined operators, the number of bits to shift is computed as follows:
When the type of x is int or uint, the shift count is given by the low-order five bits of count. In other words, the shift count is computed from count & 0x1F.
When the type of x is long or ulong, the shift count is given by the low-order six bits of count. In other words, the shift count is computed from count & 0x3F.
If the resulting shift count is zero, the shift operators simply return the value of x.
A few more notes for the novice programmer:
Why use shit operators? They don't seem to do much. Well, there are 2 reasons:
they are fast. really fast. Because nearly all CPUs have shift registers, meaning the shifting operation is done in the hardware, in the minimum amount of effort (cycles).
because they are fast, a lot of protocols and standards are designed to take advantage of this. For example IP address operations, checking a CRC, graphic operations etc.
"The shift operator is essentially "mod" the width of the data."
Rubbish! If the amount of the shift is greater than, or equal to, the width of the data, the result is undefined. Do not expect the same 'mod' operation that you happen to have seen, to happen with different compilers, or different versions of the same compiler, or in different shift situations in the same program, or when anything else changes. That's what 'undefined' means.