출처 : C++ 실력 완성 올인원 패키지 Online.(fastcampus)
비트 연산자의 NOT은 각 비트가 0->1, 1->0으로 반전됨!
결합성은 오른쪽에서 왼쪽 ⬅⬅➡
#include <iostream>
using namespace std;
int main()
{
{
// Not 연산자(~)
// 0 -> 1
// 1 -> 0
}
{
// 0000,0000,0000,0000,0000,0000,0000,0000 (0)
int num = 0;
// 1111,1111,1111,1111,1111,1111,1111,1111 (-1)
// 1은 sign bit이므로 -
// 나머지 bit에 다시 NOT 연산 후 +1을 하면
// 000,0000,0000,0000,0000,0000,0000,0001 즉 -1
cout << ~num << endl;
}
// unsigned int의 경우
{
// 0000,0000,0000,0000,0000,0000,0000,0000 (0)
unsigned int num = 0;
// 1111,1111,1111,1111,1111,1111,1111,1111 (2^32 - 1)
cout << ~num << endl;
}
&
연산자가=
연산자보다 우선순위가 높기 때문에()
괄호를 안해줘도 됨.
{
// AND 연산자(&)
// 1 & 1 == 1
// 1 & 0 == 0
// 0 & 1 == 0
// 0 & 0 == 0
}
{
int num0 = 5;
int num1 = 10;
int result = num0 & num1;
cout << result << endl; // 0이 나옴.
// 0000,0101 == 5 == 4 + 1 == 2^2 + 2^0
// 0000,1010 == 10 == 8 + 2 == 2^3 + 2^1
// 0000,0000 == 0
}
이걸 어디다 쓰지...? 출석부 프로그램을 만든다고 가정 하자. 한달치 출석 현황을 판단하기 위해서
4byte짜리 정수
면 한 명의 한달 치 출석 여부를 알 수 있다.
{
// AND 연산자를 이용하여 flag가 존재하는지 체크
uint32_t attendanceBook = 5;
if (attendanceBook & (int)pow(2, 0))
cout << "1st" << endl;
if (attendanceBook & (int)pow(2, 1))
cout << "2nd" << endl;
if (attendanceBook & (int)pow(2, 2))
cout << "3th" << endl;
if (attendanceBook & ((int)pow(2, 0) + (int)pow(2, 1)))
cout << "1 or 2" << endl;
int flag = (int)pow(2, 0) + (int)pow(2, 2);
// 연산자 우선순위 & < == 이므로 괄호 꼭 필요함!✒
if ((attendanceBook & flag) == flag)
cout << "1 and 3" << endl;
// 0000,0000,0000,0000,0000,0000,0000,0101 = 5
// 0000,0000,0000,0000,0000,0000,0000,0001 = 1 AND // 1일 체크
// 0000,0000,0000,0000,0000,0000,0000,0001 = 1 // 1일 출석
// 0000,0000,0000,0000,0000,0000,0000,0010 = 1 AND // 2일 체크
// 0000,0000,0000,0000,0000,0000,0000,0000 = 0 // 2일 결석
}
아래 처럼 출석 처리를 할 때(특정 위치의 비트를 1로 바꿔주고 싶을 때) + 연산자보단 OR 연산자를 활용하면 중복 여부를 신경쓸 필요가 없게된다.
{
// OR 연산자(|)
// 1 | 1 == 1
// 1 | 0 == 1
// 0 | 1 == 1
// 0 | 0 == 0
}
{
// OR 연산자를 이용하여 flag를 추가
uint32_t attendanceBook = 0u;
// 첫째 날 출석 처리
attendanceBook |= (int)pow(2, 0);
cout << attendanceBook << endl;
// 중복해서 같은 날에 출석을 해도 문제가 없다.
attendanceBook |= (int)pow(2, 0);
cout << attendanceBook << endl;
// 0000,0000,0000,0000,0000,0000,0000,0000 = 0
// 0000,0000,0000,0000,0000,0000,0000,0001 = 1 OR // 1일 출석
// 0000,0000,0000,0000,0000,0000,0000,0001 = 1
}
NOT 과 AND 연산을 활용하여 특정 위치의 bit를 0으로 바꿔주고 싶을 때 사용!
{
uint32_t attendanceBook = 5u;
// 셋째 날 결석 처리
attendanceBook &= ~((int)pow(2, 2));
// 0000,0000,0000,0000,0000,0000,0000,0101 = 5
// 1111,1111,1111,1111,1111,1111,1111,1011 AND
// 0000,0000,0000,0000,0000,0000,0000,0001 = 1
}
어떤 수를 0으로, 0을 어떤 수로 바꿔주는 토글하는데 사용될 수 있다. 어떤 수 ^ 어떤 수 = 0, 0 ^ 어떤 수 = 어떤 수
{
// XOR
// 1 ^ 1 == 0
// 1 ^ 0 == 1
// 0 ^ 1 == 1
// 0 ^ 0 == 0
}
{
int num0 = 5;
int num1 = 10;
cout << (num0 ^ num1) << endl;
// 0000,0101 = 5
// 0000,1010 = 10
// 0000,1111 = 15
}
{
// XOR 를 이용하여 출석/결석 토글
uint32_t attendanceBook = 0u;
attendanceBook ^= (int)pow(2, 0); // 0001
cout << attendanceBook << endl;
attendanceBook ^= (int)pow(2, 0); // 0001 ^ 0001 == 0000
cout << attendanceBook << endl;
attendanceBook ^= (int)pow(2, 0); // 0000 ^ 0001 == 0001
cout << attendanceBook << endl;
}
XOR는 교환법칙과 결합법칙이 성립한다.
{
// 홀수번 있는 단 한개의 수를 구하기
int a = 1, b = 3, c = 2, d = 1, e = 2;
cout << (a ^ b ^ c ^ d ^ e) << endl;
cout << (a ^ d ^ c ^ e ^ b) << endl; // 교환 법칙
// a ^ d = 0, c^e = 0, 0^b -> b
}
{
// << 연산자
// 0000,0001
// 0000,1000
cout << (1 << 3) << endl;
// << 한 번 할 때 마다 2배
cout << (1 << 0) << endl;
cout << (1 << 1) << endl;
cout << (1 << 2) << endl;
cout << (1 << 3) << endl;
// 값의 잘림(오버 플로우)
int num = 2200000000;
num <<= 2;
// 10000011001000010101011000000000
// 00001100100001010101100000000000
cout << num << endl;
// pow 연산을 사용하지 않고 출석 처리
int attendanceBook = 0u;
attendanceBook |= (1 << 2);
cout << attendanceBook << endl;
}
{
// >> 연산자
// 값의 잘림(언더 플로우)
cout << (1 >> 1) << endl;
// >> 한 번 할 때 마다 절반
cout << (16 >> 1) << endl;
cout << (8 >> 1) << endl;
cout << (4 >> 1) << endl;
cout << (2 >> 1) << endl;
cout << (1 >> 1) << endl;
cout << (14 >> 1) << endl; // 7
cout << (15 >> 1) << endl; // 7 잘려서 나머지 없어짐
cout << (14 >> 2) << endl; // 3 잘려서 나머지 없어짐
cout << (15 >> 2) << endl; // 3 잘려서 나머지 없어짐
}