Bitwise shift operators, << and >>, are used to manipulate the individual bits of enteger values. These operators work on the binary representation of data, specifically the two's complement form for signed integers.
Left Shift Operator (<<)
The left shift operator moves bits to the left by a specified number of positions. As bits move out from the high-order end, they are discarded, and the resulting gaps on the low-order end are filled with zeros.
Mathematically, for an integer x shifted left by n bits (x << n), the result is often equivalent to multiplying x by 2 to the power of n, provided the value does not overflow the limits of its data type.
Right Shift Operator (>>)
The right shift operator moves bits toward the lower-order positions. The bits shifted off the right end are discarded. The treatment of the vacated positions on the left depends on the system and the type of shift used:
- Logical Right Shift: The vacated bits on the left are always filled with zeros. This is typically applied to unsigned integers.
- Arithmetic Right Shift: The vacated bits are filled with the value of the original sign bit (0 for positive numbers, 1 for negative numbers). This preserves the mathematical sign of the value. Most modern C compilers implement arithmetic right shifts for signed integer types.
Implementation Example
The following code demonstrates the behavior of shift operators using 8-bit signed characters to highlight how bits overflow and how the sign bit is handled.
#include <stdio.h>
int main() {
signed char initialVal = 20; // Binary: 00010100
signed char negVal = -20; // Two's complement: 11101100
// Performing a left shift
// 00010100 shifted left by 1 becomes 00101000 (40)
signed char leftShifted = initialVal << 1;
// Performing a right shift
// 11101100 shifted right by 1 becomes 11110110 (-10) via arithmetic shift
signed char rightShifted = negVal >> 1;
printf("Original Positive: %d, Left Shifted: %d\n", initialVal, leftShifted);
printf("Original Negative: %d, Right Shifted: %d\n", negVal, rightShifted);
return 0;
}
Usage Constraints and Undefined Behavior
When using shift operators, certain rules must be followed to avoid unpredictable results:
- Integer Types Only: Shifts are only defined for integer types (e.g.,
int,char,long). They cannot be applied to floating-point numbers likefloatordouble. - Non-Negative Shift Count: The number of positions to shift must be a non-negative value. Shifting by a negative integer is undefined behavior.
- Width Limits: The shift count must be less than the total number of bits in the left-hand operand. For example, shifting a 32-bit integer by 32 or more positions is considered undefined behavior in C.