왼쪽 시프트 및 오른쪽 시프트 연산자: <<
및 >>
비트 시프트 연산자는 정수 또는 열거형 형식 식의 비트를 오른쪽으로 이동하는 오른쪽 시프트 연산자(>>
)와 비트를 왼쪽으로 이동하는 왼쪽 시프트 연산자(<<
)입니다. 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
이 부호 있는 형식이고 음수인 경우 결과 값은 구현 시 정의됩니다.
참고 항목
피드백
https://aka.ms/ContentUserFeedback
출시 예정: 2024년 내내 콘텐츠에 대한 피드백 메커니즘으로 GitHub 문제를 단계적으로 폐지하고 이를 새로운 피드백 시스템으로 바꿀 예정입니다. 자세한 내용은 다음을 참조하세요.다음에 대한 사용자 의견 제출 및 보기