The -shl and -shr operators were introduced with PowerShell 3.0. These operators perform bit-shifting.
The possible bit values for a byte may be represented in a table:
Bit position |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Bit value |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
For a numeric value of 78, the following bits must be set:
Bit value |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
On or off |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
When a left shift operation is performed, every bit is moved one to the left. Say we run this expression:
78 -shl 1
The result is 156, which may be expressed in the bit table:
Bit value |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
Before shift |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
After shift |
1 |
0 |
0 |
1 |
1 |
1 |
0 |
0 |
Shifting one bit to the right will reverse the operation:
PS> 156 -shr 1
78
When converting values using left or right shifting, bits that are set and right-shifted past the rightmost bit (bit value 1) become 0, for example:
PS> 3 -shr 1
1
This may be described in the following table. Bits that end up in the right-most column are discarded:
Bit value |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
Out of range |
Before shift |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
|
After shift |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
If the numeric value is of a specific numeric type, the resulting number cannot exceed the maximum value for the type. For example, a Byte has a maximum value of 255; if the value of 255 is shifted one bit to the left, the resulting value will be 254:
PS> ([Byte]255) -shl 1
254
Shifting out of range may be shown in a table:
Bit value |
Out of range |
128 |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
Before shift |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
|
After shift |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
If the value were capable of being larger, such as a 16 or 32-bit integer, the value would be allowed to increase as it no longer falls out of range:
PS> ([Int16]255) -shl 1
510
Bit shifting as this is easiest to demonstrate with unsigned types such as Byte, UInt16, UInt32, and UInt64. Unsigned types cannot support values lower than 0 (negative numbers).
Signed types, such as SByte, Int16, Int32, and Int64, sacrifice their highest-order bit to indicate whether the value is positive or negative. For example, this table shows the bit positions for a Signed Byte (SByte):
Bit position |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Bit value |
Signing |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
The preceding bit values may be used to express number between 127 and -128. The binary forms of 1 and -1 are shown as an example in the following table:
Bit value |
Signing |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
-1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
For a signed type, each bit (except for signing) adds to a minimum value:
- When the signing bit is not set, add each value to 0
- When the signing bit is set, add each value to -128
Applying this to left shift, if the value of 64 is shifted one bit to the left, it becomes -128:
PS> ([SByte]64) -shl 1
-128
The shift into the signing bit can be expressed in a table:
Bit value |
Signing |
64 |
32 |
16 |
8 |
4 |
2 |
1 |
Before shift |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
After shift |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
Shift operations such as these are common in the networking world. For example, the IP address 192.168.4.32 may be represented in a number of different ways:
- In hexadecimal: C0A80420
- As an unsigned 32-bit integer: 3232236576
- As a signed 32-bit integer: -1062730720
The signed and unsigned versions of an IP address are calculated using left shift. For example, the IP address 192.168.4.32 may be written as a signed 32-bit integer (Int32):
(192 -shl 24) + (168 -shl 16) + (4 -shl 8) + 32