비트 단위 연산자(Bitwise operators)
비트 단위 연산자는 변수 내의 비트(bit)를 조작할 수 있다. 이를 사용하면 메모리를 절약할 수도 있다.
요즘에는 하드웨어의 발달로 유지보수가 쉬운 코딩을 하는 것이 더 좋은 방법이라고 한다.
때문에 비트 단위 연산자는 특정 상황을 제외하고는 잘 쓰이지는 않는다.
우선 비트 단위 연산자에는 6가지의 연산자가 존재한다.
Operator | Symbol | Form | Operation |
left shift | << | x << y | all bits in x shifted left y bits |
right shift | >> | x >> y | all bits in x shifted right y bits |
bitwise NOT | ~ | ~x | all bits in x flipped |
bitwise AND | & | x & y | each bit in x AND each bit in y |
bitwise OR | l | x l y | each bit in x OR each bit in y |
bitwise XOR | ^ | x ^ y | each bit in x XOR each bit in y |
비트 단위라서 2진수로 계산을 하게 된다.
비트 NOT 연산자
비트 NOT 연산자(~)는 각 비트에서 0과 1을 서로 바꾼다. 결괏값은 자료형의 크기에 따라 달라진다.
//4bit
4 = 0100
~4 = 1011 = 11
//8bit
4 = 0000 0100
~4 = 1111 1011 = 251
비트 AND / OR / XOR 연산자
비트 AND 연산자(&)와 비트 OR 연산자(|)는 논리 연산자 AND(&&)와 OR(||)과 비슷한 느낌으로 동작한다.
논리 연산자가 bool값으로 평가하는 대신 비트 연산자는 각각의 비트 하나하나에 적용이 된다.
비트 OR 연산자는 논리 OR 연산자와 비슷하게 비트 두개 중 하나라도 1이면 무조건 1로 평가된다.
//5 | 6
0 1 0 1 // 5
0 1 1 0 // 6
//결과
0 1 1 1 // 7
비트 AND 연산자는 논리 AND 연산자와 비슷하게 두 개의 비트 모두 1인 경우에만 1로 평가된다.
//5 & 6
0 1 0 1 // 5
0 1 1 0 // 6
//결과
0 1 0 0 // 4
마지막 비트 XOR 연산자는 두 연산자를 평가할 때, 한 개의 피연산자만 1인 경우에만 1로 평가한다.
즉, 두 비트 모두 1인 경우에는 0으로 평가하는 것이다.
// 5 ^ 6
0 1 0 1 // 5
0 1 1 0 // 6
//결과
0 0 1 1 // 3
비트 단위 연산자에 대입 연산자를 적용할 수도 있는데, 기존의 산술 연산자에서 사용하던 것처럼 사용할 수 있다.
예를 들어 x = x << 1을 쓰는 대신 x <<= 1처럼 쓸 수 있는 것이다.
시프트연산자(Shift Operator)
시프트 연산자에 대해서 생소할 수도 있겠지만, 우리는 이미 코딩을 하면서 어디선가 많이 봐왔던 것이다.
바로 cout, cin 사용할 때 함께 쓰던 <<, >>이다.
시프트의 사전적 의미로는 이동, 옮긴다는 뜻을 가지고 있다. <<, >>을 보면 방향을 가리키는 모습처럼 보인다.
비트 연산자 중 하나인 시프트 연산자는 마찬가지로 2진수에서 비트 단위로 이동시키는 연산자를 말한다.
Left Shift / Right Shift 연산자
10진수의 정수 10을 2진수로 바꿔 8bit의 크기로 비트를 표현하면 다음과 같이 나올 것이다.
0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 |
여기서 Left Shift 연산자를 사용한다면 10 << 2과 같이 표현할 수 있다.
시프트 연산자 앞에 붙은 피연산자 10은 정수 10을 말하는 것이고, <<는 왼쪽으로 시프트 하라는 뜻의 연산자이다.
그리고 뒤에 붙은 2는 2만큼 칸을 이동하라는 뜻이다.
즉, 정수 10을 2진수로 변환한 비트 값을 왼쪽으로 2칸씩 이동하라는 말이 된다.
그래서 Left Shift 연산자 10 << 2의 식은 다음과 같은 결과가 나온다.
0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
위의 2진수를 다시 10진수로 변환하면 40의 값이 나오는 것을 볼 수 있다.
그렇다면 반대로 Right Shift 연산자 10 >> 2의 결과는 예상할 수 있을 것이다.
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
위의 결과가 발생하게 되는데, 여기에서 문제점이 있다. 바로 비트 범위 밖으로 1이 넘어가 버리면서 사라져 버린 것인데,
시프트 연산자는 허용범위를 넘어가버리면 그냥 값이 사라져 버리는 특징이 있다.
이처럼 데이터 손실이 발생할 수도 있으니 주의해야 한다.
Left Shift 연산자의 식과 결과를 보면서 한 가지 공식을 알 수 있게 된다.
Left Shift 연산자를 통해 정수 10이 40이 되는 것을 살펴보면 10 * 4, 그리고 4는 2의 2제곱이라고 한다면 딱 맞아떨어진다.
따라서 10 << 2는 10 * 2의 2제곱과 같다는 것을 알 수 있다. 이를 통해 x << n의 식은 x * 2^n이라는 공식과 성립하게 된다.
'C++' 카테고리의 다른 글
9/6_리플렉션2 (0) | 2023.09.06 |
---|---|
STL deque / map (0) | 2023.01.17 |
C++ 배우기 28(WinAPI) (0) | 2022.12.05 |
C++ 배우기 27(함수포인터) (0) | 2022.12.01 |
C++ 배우기 26(LValue / RValue) (0) | 2022.11.30 |