왼쪽 시프트 및 오른쪽 시프트 연산자: <<>>

비트 시프트 연산자는 정수 또는 열거형 형식 식의 비트를 오른쪽으로 이동하는 오른쪽 시프트 연산자(>>)와 비트를 왼쪽으로 이동하는 왼쪽 시프트 연산자(<<)입니다. 1

구문

shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

설명

Important

다음 설명 및 예제는 x86 및 x64 아키텍처용 Windows에서 유효합니다. ARM 디바이스용 Windows에서는 왼쪽 시프트 및 오른쪽 시프트 연산자의 구현이 크게 다릅니다. 자세한 내용은 Hello ARM 블로그 게시물의 "Shift Operators" 섹션을 참조하세요.

왼쪽 시프트

왼쪽 시프트 연산자를 사용하면 shift-expression에 비트가 additive-expression에 의해 지정된 위치 수만큼 왼쪽으로 이동됩니다. 시프트 연산으로 비워진 비트 위치는 0으로 채워집니다. 왼쪽 시프트는 논리 시프트입니다(부호 비트를 포함해 끝에서 벗어나 이동한 비트는 무시됨). 비트 시프트 종류에 대한 자세한 내용은 Bitwise 시프트를 참조하세요.

다음 예제에서는 부호 없는 숫자를 사용하는 왼쪽 시프트 연산을 보여 줍니다. 예제에서는 값을 비트 집합으로 나타내어 비트에서 어떤 일이 발생하는지 보여 줍니다. 자세한 내용은 비트 세트 클래스를 참조하세요.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    unsigned short short1 = 4;
    bitset<16> bitset1{short1};   // the bitset representation of 4
    cout << bitset1 << endl;  // 0b00000000'00000100

    unsigned short short2 = short1 << 1;     // 4 left-shifted by 1 = 8
    bitset<16> bitset2{short2};
    cout << bitset2 << endl;  // 0b00000000'00001000

    unsigned short short3 = short1 << 2;     // 4 left-shifted by 2 = 16
    bitset<16> bitset3{short3};
    cout << bitset3 << endl;  // 0b00000000'00010000
}

부호 비트가 영향을 받도록 부호 있는 숫자를 왼쪽 시프트하면 결과가 정의되지 않습니다. 다음 예제에서는 1비트를 왼쪽에서 부호 비트 위치로 이동하면 어떻게 되는지 보여 집니다.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    short short1 = 16384;
    bitset<16> bitset1(short1);
    cout << bitset1 << endl;  // 0b01000000'00000000

    short short3 = short1 << 1;
    bitset<16> bitset3(short3);  // 16384 left-shifted by 1 = -32768
    cout << bitset3 << endl;  // 0b10000000'00000000

    short short4 = short1 << 14;
    bitset<16> bitset4(short4);  // 4 left-shifted by 14 = 0
    cout << bitset4 << endl;  // 0b00000000'00000000
}

오른쪽 시프트

오른쪽 시프트 연산자를 사용하면 shift-expression에 비트 패턴이 additive-expression에 의해 지정된 수만큼 오른쪽으로 이동됩니다. 부호 없는 숫자의 경우 시프트 연산으로 비워진 비트 위치는 0으로 채워집니다. 부호 있는 숫자의 경우 부호 비트는 비워진 비트 위치를 채우는 데 사용됩니다. 즉, 숫자가 양수이면 0이 사용되고 숫자가 음수이면 1이 사용됩니다.

Important

부호 있는 음수의 오른쪽 시프트 결과는 구현에 따라 다릅니다. Microsoft C++ 컴파일러는 부호 비트를 사용하여 비워진 비트 위치를 채우지만 다른 구현에서도 그렇게 한다는 보장은 없습니다.

이 예제에서는 부호 없는 숫자를 사용하는 오른쪽 시프트 연산을 보여 줍니다.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    unsigned short short11 = 1024;
    bitset<16> bitset11{short11};
    cout << bitset11 << endl;     // 0b00000100'00000000

    unsigned short short12 = short11 >> 1;  // 512
    bitset<16> bitset12{short12};
    cout << bitset12 << endl;     // 0b00000010'00000000

    unsigned short short13 = short11 >> 10;  // 1
    bitset<16> bitset13{short13};
    cout << bitset13 << endl;     // 0b00000000'00000001

    unsigned short short14 = short11 >> 11;  // 0
    bitset<16> bitset14{short14};
    cout << bitset14 << endl;     // 0b00000000'00000000
}

다음 예제에서는 부호 있는 양수를 사용하는 오른쪽 시프트 연산을 보여 줍니다.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    short short1 = 1024;
    bitset<16> bitset1(short1);
    cout << bitset1 << endl;     // 0b00000100'00000000

    short short2 = short1 >> 1;  // 512
    bitset<16> bitset2(short2);
    cout << bitset2 << endl;     // 0b00000010'00000000

    short short3 = short1 >> 11;  // 0
    bitset<16> bitset3(short3);
    cout << bitset3 << endl;     // 0b00000000'00000000
}

다음 예제에서는 부호 있는 음수를 사용하는 오른쪽 시프트 연산을 보여 줍니다.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    short neg1 = -16;
    bitset<16> bn1(neg1);
    cout << bn1 << endl;  // 0b11111111'11110000

    short neg2 = neg1 >> 1; // -8
    bitset<16> bn2(neg2);
    cout << bn2 << endl;  // 0b11111111'11111000

    short neg3 = neg1 >> 2; // -4
    bitset<16> bn3(neg3);
    cout << bn3 << endl;  // 0b11111111'11111100

    short neg4 = neg1 >> 4; // -1
    bitset<16> bn4(neg4);
    cout << bn4 << endl;  // 0b11111111'11111111

    short neg5 = neg1 >> 5; // -1
    bitset<16> bn5(neg5);
    cout << bn5 << endl;  // 0b11111111'11111111
}

시프트 및 승격

시프트 연산자 양쪽에 있는 식은 정수 계열 형식이어야 합니다. 정수 승격은 표준 변환에 설명된 규칙에 따라 수행됩니다. 결과의 형식은 승격된 shift-expression 형식과 동일합니다.

다음 예제에서는 char 형식의 변수가 int(으)로 승격됩니다.

#include <iostream>
#include <typeinfo>

using namespace std;

int main() {
    char char1 = 'a';

    auto promoted1 = char1 << 1;   // 194
    cout << typeid(promoted1).name() << endl;  // int

    auto promoted2 = char1 << 10;  // 99328
    cout << typeid(promoted2).name() << endl;  // int
}

세부 정보

시프트 작업의 결과는 additive-expression(이) 음수이거나 만약 additive-expression(이)가 (승격된) shift-expression 비트 수보다 크거나 같은 경우 정의되지 않습니다. 만약 additive-expression(이)가 0이면 교대 근무 작업이 수행되지 않습니다.

#include <iostream>
#include <bitset>

using namespace std;

int main() {
    unsigned int int1 = 4;
    bitset<32> b1{int1};
    cout << b1 << endl;    // 0b00000000'00000000'00000000'00000100

    unsigned int int2 = int1 << -3;  // C4293: '<<' : shift count negative or too big, undefined behavior
    unsigned int int3 = int1 >> -3;  // C4293: '>>' : shift count negative or too big, undefined behavior
    unsigned int int4 = int1 << 32;  // C4293: '<<' : shift count negative or too big, undefined behavior
    unsigned int int5 = int1 >> 32;  // C4293: '>>' : shift count negative or too big, undefined behavior
    unsigned int int6 = int1 << 0;
    bitset<32> b6{int6};
    cout << b6 << endl;    // 0b00000000'00000000'00000000'00000100 (no change)
}

각주

1 다음은 C++11 ISO 사양(INCITS/ISO/IEC 14882-2011[2012]), 섹션 5.8.2 및 5.8.3의 시프트 연산자 설명입니다.

E1 << E2의 값은 E1 왼쪽 이동된 E2 비트 위치입니다. 비워진 비트는 0으로 채워집니다. 만약 E1에 부호 없는 형식이 있는 경우 결과 값은 E1 × 2 E2입니다. 결과 형식에서 나타낼 수 있는 최대 값 보다 한 개 더 줄어드는 모듈입니다. 그렇지 않으면 만약 E1에 부호 있는 형식과 음수가 아닌 값이 있고 E1 × 2E2가 결과 형식의 해당 부호 없는 형식으로 나타낼 수 있는 경우 결과 형식으로 변환된 해당 값이 결과 값입니다. 그렇지 않으면 동작이 정의되지 않았습니다.

E1 >> E2의 값은 E1 오른쪽 이동된 E2 비트 위치입니다. 만약 E1에 부호 없는 형식이 있거나 E1에 부호 있는 형식과 음수가 아닌 값이 있는 경우 결과 값은 E1/2E2 몫의 정수 부분입니다. E1이 부호 있는 형식이고 음수인 경우 결과 값은 구현 시 정의됩니다.

참고 항목

이항 연산자가 있는 식
C++ 기본 제공 연산자, 우선 순위 및 결합성