Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C/C++ 왼쪽 시프트(<<)와 오른쪽 시프트(>>) 연산자 완벽 가이드

왼쪽 시프트 연산자(<<)

왼쪽 시프트 연산자는 왼쪽 피연산자의 값을 오른쪽 피연산자가 지정한 비트 수만큼 왼쪽으로 이동시킵니다. 비트가 왼쪽으로 밀려나면서 오른쪽의 빈 자리는 0으로 채워집니다.

왼쪽 시프트는 수학적으로 2의 거듭제곱 곱셈과 같습니다. 즉, x << nx × 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 >> nx ÷ 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의 거듭제곱 배율 계산에는 시프트 연산을 활용하는 것이 효율적입니다.