비트 연산자로 N번째 비트 변경하기
비트 단위로 연산을 수행하는 비트 연산자를 통해 원하는 비트 자리 수를 간단하게 변경하는 방법을 알아보자.
[비트 연산자]
여기서 사용할 연산자만 소개
- | (OR)
- & (AND)
- ~ (NOT)
- << (left shift)
- >> (right shift)
1바이트 짜리 unsigned char 타입을 통해 비트 연산을 해보자. 먼저 1바이트는 8비트로 true/false의 값을 8개 저장할 수 있다.
다음과 같이 unsigned char 타입의 변수를 0으로 초기화 후 bitset 클래스를 통해 이진수 형식으로 출력해보자.
bitset 클래스는 <bitset> 헤더 파일을 include 해야한다.
#include <bitset>
#include <iostream>
void main()
{
unsigned char c = 0;
std::cout << std::bitset<8>(c) << std::endl;
}
bitset 클래스는 템플릿 매개변수로 출력을 원하는 비트 수를 받는다. 위의 코드는 c를 8비트로 출력한다.
따라서 위 결과는 0을 이진수로 표현한 0000 0000으로 나올 것이다. (여기선 가독성을 위해 4칸마다 띄어쓰기)
[첫 번째 비트 0을 비트 1로 만들기]
그럼 c의 첫 번째 비트를 1로 set 하고 싶다고 생각해보자. 즉 0000 0000을 0000 0001로 만들고 싶다. 0을 1로 변경하기 위해선 OR이라는 비트 연산을 통해 얻어내야 한다. 0과 1을 OR 연산하면 1이 되는 성질을 이용한다. 나머지 비트는 모두 0으로 유지한다.
#include <bitset>
#include <iostream>
void main()
{
unsigned char c = 0;
c |= 1; // 0000 0000 OR 0000 0001
std::cout << std::bitset<8>(c) << std::endl; // 0000 0001
}
[두 번째 이상 비트를 비트 1로 만들기]
나머지 비트는 그대로 유지하고, 두번째 비트를 1로 만들기 위해선 0000 0010 을 OR 연산해주어야 한다.
0은 OR연산을 하더라도 기존 비트 값을 그대로 유지하기 때문에 원하는 비트를 제외한 나머지 비트는 모두 0이여야 한다.
0000 0010은 1을 1만큼 left-shift 연산을 수행하면 된다. shift 연산은 원하는 방향으로 모든 비트를 이동시킨다.
따라서 아래와 같이 1을 왼쪽으로 1 shift하여 c와 OR 연산을 해주면 두번째 비트가 1로 set된다.
#include <bitset>
#include <iostream>
void main()
{
unsigned char c = 0;
c |= 1; // 0000 0000 OR 0000 0001
c |= (1 << 1) // 0000 0001 OR 0000 0010
std::cout << std::bitset<8>(c) << std::endl; // 0000 0011
}
위의 결과만으로도 n번째 비트를 1로 set하기 위해선 얼마만큼 shift 연산을 하여 OR연산을 해야하는지 이해할 수 있을 것이다.
[첫 번째 비트를 0으로 만들기]
이번엔 위에서 변경한 c의 첫 번째 비트와 두 번째 비트를 다시 0으로 만들어보자. 1은 단순히 원하는 비트만 1로 만든 후 c와 OR연산을 해주면 됐지만, 0으로 만들기 위해선 AND연산이 필요하다. AND는 기존 비트에 영향을 주지 않으려면 0으로 만드려는 비트를 제외한 모든 비트가 1이여야 한다. 예를 들어 11의 첫 번째 비트만 0으로 만들고 싶다면 10과 AND연산을 해야한다.
0000 0011을 0000 0010으로 만들기 위해선 1111 1110과 AND연산을 해야한다.
1111 1110은 역으로 생각해보면 0000 0001의 모든 비트를 NOT(~) 연산을 하여 각 비트를 뒤집은 수이다. 따라서 다음과 같이 1을 NOT 연산 후 c와 AND 연산을 해준다.
#include <bitset>
#include <iostream>
void main()
{
unsigned char c = 0;
c |= 1; // 0000 0000 OR 0000 0001
c |= (1 << 1); // 0000 0001 OR 0000 0010
c &= ~(1 << 0); // 0000 0011 AND 1111 1110
std::cout << std::bitset<8>(c) << std::endl; // 0000 0010
}
[두 번째 비트를 0으로 만들기]
이번엔 두 번째 비트를 0으로 만들어보자. 이전과 동일하게 0000 0010의 두 번째 비트를 0으로 만들기 위해선 두 번째 비트를 제외한 모든 비트가 1인 수와 AND연산을 하면된다.
1111 1101은 NOT 연산을 하면 0000 0010이 된다. 즉 1을 1만큼 left-shift 후에 NOT 연산을 하면 1111 1101이 된다.
이 후 c와 AND 연산을 하면 원하는 두 번째 비트가 0이 된다.
#include <bitset>
#include <iostream>
void main()
{
unsigned char c = 0;
c |= 1; // 0000 0000 OR 0000 0001
c |= (1 << 1); // 0000 0001 OR 0000 0010
c &= ~(1 << 0); // 0000 0011 AND 1111 1110
c &= ~(1 << 1); // 0000 0010 AND 1111 1101
std::cout << std::bitset<8>(c) << std::endl; // 0000 0000
}
여기까지 간단한 비트를 계산법을 알아봤고, 지금까지의 내용을 이해했다면 원하는 자릿수도 제어할 수 있을 것이다.
'C,C++ > Etc' 카테고리의 다른 글
Visual Studio C++ 17 사용하도록 설정하기 (0) | 2020.06.25 |
---|---|
메모리 정렬과 패킹 (2) | 2020.05.19 |
[C++] 소수점 n번째 자리에서 반올림 하기 | std::round (0) | 2020.02.26 |
[C++] 한 줄 짜리 지식 모음 (0) | 2020.01.20 |
내가 따라하는 C++ 코딩표준 (0) | 2020.01.02 |
댓글