왼쪽 시프트 연산자(<<)
왼쪽 시프트 연산자는 왼쪽 피연산자의 값을 오른쪽 피연산자가 지정한 비트 수만큼 왼쪽으로 이동시킵니다. 비트가 왼쪽으로 밀려나면서 오른쪽의 빈 자리는 0으로 채워집니다.
왼쪽 시프트는 수학적으로 2의 거듭제곱 곱셈과 같습니다. 즉, x << n은 x × 2ⁿ과 동일한 결과를 냅니다. 예를 들어 28을 1비트 왼쪽 시프트하면 56이 되고, 2비트 시프트하면 112가 됩니다.
예제 코드
#include <stdio.h>
int main() {
int y = 28; // 2진수: 11100
int i = 0;
for(i; i<=3; ++i)
printf("Left shift by %d: %d\n", i, y<<i);
return 0;
}
실행 결과
Left shift by 0: 28
Left shift by 1: 56
Left shift by 2: 112
Left shift by 3: 224
28(2진수 11100)을 3비트 왼쪽 시프트하면 224(2진수 11100000)가 되는 것을 확인할 수 있습니다. 비트가 한 칸 이동할 때마다 값이 정확히 2배씩 커집니다.
오른쪽 시프트 연산자(>>)
오른쪽 시프트 연산자는 왼쪽 피연산자의 값을 오른쪽 피연산자가 지정한 비트 수만큼 오른쪽으로 이동시킵니다. 오른쪽으로 밀려나간 비트는 버려지며, 양수의 경우 왼쪽 빈 자리는 0으로 채워집니다.
오른쪽 시프트는 2의 거듭제곱 나눗셈과 같습니다. 즉, x >> n은 x ÷ 2ⁿ과 동일합니다. 예를 들어 10을 1비트 오른쪽 시프트하면 5가 됩니다.
예제 코드
#include <stdio.h>
int main() {
int x = 10; // 2진수: 1010
int i = 0;
for(i; i<2; i++)
printf("Right shift by %d: %d\n", i, x>>i);
return 0;
}
실행 결과
Right shift by 0: 10
Right shift by 1: 5
사용 시 주의 사항
- 부호 있는 정수: 음수에 대한 오른쪽 시프트 결과는 C 표준에서 구현 정의(implementation-defined)이므로, 컴파일러에 따라 부호 비트를 유지하는 산술 시프트 또는 0으로 채우는 논리 시프트로 동작할 수 있습니다.
- 오버플로우: 왼쪽 시프트로 유효 비트 범위를 초과하면 데이터가 손실되며, 부호 있는 정수의 경우 미정의 동작(undefined behavior)이 발생할 수 있습니다.
- 성능: 시프트 연산은 곱셈·나눗셈보다 빠르게 처리되므로, 2의 거듭제곱 배율 계산에는 시프트 연산을 활용하는 것이 효율적입니다.