따배씨++ (3.9 bit flag & mask)

김동우·2021년 4월 14일
0

안녕하십니까. 김동우입니다.

이번 노트에서는 비트 플래그와 마스크에 대해서 얘기할까 합니다.

오늘은 소스가 길고, 많으니 나름대로의 구분을 하겠습니다.

  1. bit_flag.cpp
#include <iostream>
#include <bitset>
using namespace std;

int main()
{
    // 이 시간은 배열을 더 최적화하여 사용하기 위한 시간이다.
    // 즉, 실전용 수업이다.

    /*
     bool item1_flag = false;
     bool item2_flag = false;
     bool item3_flag = false;
     bool item4_flag = false;
     ...
     
     1byte 변수 하나로 아이템 8개를 컨트롤 할 수 있다. (bool 1bit on-off)
    */

    // opt 선언 - 하드코딩
    const unsigned char opt0 = 1 << 0;
    const unsigned char opt1 = 1 << 1;
    const unsigned char opt2 = 1 << 2;
    const unsigned char opt3 = 1 << 3;
    const unsigned char opt4 = 1 << 4;
    const unsigned char opt5 = 1 << 5;
    const unsigned char opt6 = 1 << 6;
    const unsigned char opt7 = 1 << 7;

    /*
    cout << std::bitset<8>(opt0) << endl;
    cout << std::bitset<8>(opt1) << endl;
    cout << std::bitset<8>(opt2) << endl;
    cout << std::bitset<8>(opt3) << endl;
    cout << std::bitset<8>(opt4) << endl;
    cout << std::bitset<8>(opt5) << endl;
    cout << std::bitset<8>(opt6) << endl;
    cout << std::bitset<8>(opt7) << '\n' << endl;
    */
    // output 생략 이전 강의 참고

    // output : 00000001

    unsigned char items_flag = 0;

    cout << std::bitset<8>(items_flag) << '\n' << endl;
    // output : 00000000
    // 스위치 on off 개념으로 생각하면 
    // 8개의 bool type 변수를 사용하는 효과를 낼 수 있다.
    // 이후 opt 선언으로 올라가서 생각해보자.

    cout << " No item " << bitset<8>(items_flag) << '\n' << endl;

    // item0 on
    items_flag |= opt0;
    cout << " Item0 obtained " << bitset<8>(items_flag) 
         << '\n' << endl;

    // item3 on + item0 maintain
    items_flag |= opt3;
    cout << " Item3 obtained " << bitset<8>(items_flag)
         << '\n' << endl;
    
    // item3 lost
    items_flag &= ~opt3; // AND assignment + NOT bitwise
    cout << " Item3 lost " << bitset<8>(items_flag)
         << '\n' << endl;

    // item1 check
    if(items_flag & opt1) { cout << " Has item1 " << '\n' << endl; }

    else { cout << " Not have item1 " << '\n' << endl; }

    // item0 check
    if (items_flag & opt0){ cout << " Has item0 " << '\n' << endl; }

    // obtain item 2, 3
    items_flag |= (opt2 | opt3);

    cout << std::bitset<8>(items_flag) << '\n' << endl;
    // output : 0000 1101

    if((items_flag & opt2) && !(items_flag & opt1))
    {   
        // items_flag ^= opt2;
        // items_flag ^= opt1;
        items_flag ^= (opt2 | opt1); // 상태변화는 XOR로 처리하면 편하다.
        cout << std::bitset<8>(items_flag) << endl;
    }

    return 0;
  1. bit_mask.cpp
#include <iostream>
#include <bitset>
using namespace std;

int main()
{   
    // 예시 1
    // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    // parameter 정의에 있어 bitwise operator는 상당히 유용하다.
    
    // 즉, API design에 있어 bit flag는 유용할 수 있다.

    // 예시 2
    // 프론트엔드, 그래픽 디자이너들의 경우 컬러테이블을 활용하는 경우가 많다.
    // hex code 기반으로 작성된 컬러테이블은 3byte(rgb) + 1byte(alpha)
    // 이를 RGB code로 바꿔보자. (영상처리에도 유용할 수 있겠다.)

    const unsigned int red_mask = 0xFF0000;
    const unsigned int green_mask = 0x00FF00;
    const unsigned int blue_mask = 0x0000FF;

    unsigned int pixel_color = 0xDAA520;

    cout << bitset<32>(pixel_color) << endl;
    // output : 00000000110110101010010100100000
    cout << bitset<32>(red_mask) << endl;
    cout << bitset<32>(green_mask) << endl;
    cout << bitset<32>(blue_mask) << '\n' << endl;

    //
    unsigned char red, green, blue;

    red = (pixel_color & red_mask) >> 16;
    green = (pixel_color & green_mask) >> 8;
    blue = pixel_color & blue_mask;

    cout << " Red " << bitset<8>(red) << " " << int(red) << endl;
    cout << " Green " << bitset<8>(green) << " " << int(green) << endl;
    cout << " Blue " << bitset<8>(blue)<< " " << int(blue) << endl;

    // 1, masking - 0xFF...
    // 2. extract - AND bitwise
    // 3. RGB - right shift bitwise 

    return 0;
}
  1. quiz.cpp
#include <iostream>
#include <bitset>
using namespace std;

int main()
{   
    // 1. 아래 플래그를 바꿔보세요.
    // - 기사를 봤을 때
    // - 기사의 좋아요를 클릭했을 때
    // - 기사의 좋아요를 다시 클릭했을 때
    // - 본 기사만 삭제할 때
    unsigned char option_viewed(0x01);
    unsigned char option_edited(0x02);
    unsigned char option_liked(0x04);
    unsigned char option_shared(0x08);
    unsigned char option_deleted(0x80);

    unsigned char my_article_flags = 0;

    // - 기사를 봤을 때
    my_article_flags |= option_viewed;
    

    // - 기사의 좋아요를 클릭했을 때
    my_article_flags |= option_liked;
    
    // - 기사의 좋아요를 다시 클릭했을 때
    if(my_article_flags & option_liked)
    {
        my_article_flags ^= option_liked;
    }

    // - 본 기사만 삭제할 때
    if ((my_article_flags & option_viewed) 
        && (my_article_flags & option_deleted))
    {
        my_article_flags ^= (option_deleted | option_viewed);
    }

    // 2. 아래 두 줄이 동일하게 작동하는 이유를 설명하세요
    // 초기화 이후의 두 줄
    unsigned char option4(1 << 4);
    unsigned char option5(1<<5);

    unsigned char myflags = 0;

    myflags &= ~(option4 | option5);
    myflags &= ~option4 & ~option5;
    // 드모르간의 법칙을 적용하면 간단하게 설명할 수 있다.
    // !A && !B = !(A || B)
    // !(A && B) = !A || !B

    return 0;
}
  • quiz.cpp 파일의 코드는 저 스스로의 문제풀이이기 때문에 오답이 존재할 수 있습니다. 또한 flag가 카운트되는 조건 또는 이전 상황이 코드에 존재하지 않는 것은 수업에서 배운 내용을 최대한 생략했기 때문입니다.

    그러나 실제로 flag 카운트 이전 모든 option 변수를 0으로 초기화하고, 해당 상활에 맞게 각 문항별로 값을 재할당하는 등의 코드를 추가하면 보다 쉽게 이해할 수 있습니다.

그럼 이만 이번 글은 마치도록 하겠습니다. 감사합니다.

0개의 댓글

관련 채용 정보