비트 연산자

Kiwoong Park·2023년 7월 14일
0

출처 : C++ 실력 완성 올인원 패키지 Online.(fastcampus)

0의 NOT은 -1?, 2^32-1?

비트 연산자의 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;
    }

bit의 AND, OR

&연산자가 =연산자보다 우선순위가 높기 때문에 ()괄호를 안해줘도 됨.

    {
        // 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일 결석
    }

OR 연산자

아래 처럼 출석 처리를 할 때(특정 위치의 비트를 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
    }

AND 연산자를 활용한 결석처리

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
    }

XOR 연산자

어떤 수를 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 잘려서 나머지 없어짐
    }
profile
You matter, never give up

0개의 댓글