Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C++] 구조체의 비트 필드 본문

Programming/C++

[Programming/C++] 구조체의 비트 필드

scii 2023. 1. 14. 22:20

비트 필드(Bit Fields)를 사용하면 구조체의 멤버가 차지하는 메모리 공간을 원하는 데로 조절할 수 있다. 예를 들면 멤버 a는 3비트만, b는 4비트만 차지하게 만드는 것이 가능하다.

struct Flags
{
    int a : 3;
    int b : 4;
    bool c : 1;
};

비트 필드를 사용하는 멤버는 정수 타입만 가능한데, 멤버의 뒤에 적힌 숫자가 멤버가 차지할 비트 수를 의미하게 된다. 즉 위의 구조체를 사용해서 변수를 정의하게 되면 다음과 같은 메모리 구조를 갖게 된다.

비트 필드를 사용했을 때의 메모리 구조

중간에 사용하지 않는 비트를 넣고 싶을 때는 멤버의 이름을 적어주지 않으면 된다. 이렇게 해주면 중간에 5비트는 사용하지 않은 채로 남게 된다.

struct Flags
{
    int a : 3;
    int b : 4;
    int : 5;
    bool c : 1;
};

사용하지 않는 비트

비트 필드는 비트 단위의 논리 연산을 대신해서 사용할 수 있다. 다음은 unsigned short 타입의 변수에 보관한 색상 정보에서 파란색 값만 추출해내는 예제이다.

#include <bitset>
#include <iostream>

using namespace std;

struct Pixel16 {
    unsigned int blue : 5;
    unsigned int green : 6;
    unsigned int red : 5;
};

// unsigned short 타입의 값을 Pixel16 구조체 값으로 변환하기 위한 용도로 공용체 만듦.
union Convert16 {
    Pixel16 pixel;
    unsigned short us;
};

int main(void) {
    // 한 점의 색상을 보관하는 변수
    unsigned short color = 0x1234;

    // unsigend short 타입의 값을 Pixel16 구조체 타입인 것처럼 다루기 위해 공용체 사용.
    Convert16 convert;
    convert.us = color;

    cout << "color = " << bitset<16>(color) << "(" << color << ")" << endl;
    cout << "blude = " << bitset<16>(convert.pixel.blue) << "(" << convert.pixel.blue << ")" << endl;
}


// 결과
color = 0001001000110100(4660)
blude = 0000000000010100(20)

convert.pixel을 통해서 색상 정보를 읽는다. convert.us와 convert.pixel은 같은 메모리 공간을 공유하므로 색상 정보를 읽을 수 있다. 즉, convert.us를 통해 저장할 때는 unsigned short 타입의 값이엇지만, convert.pixel을 통해 꺼내 쓸 때는 구조체 Pixel16타입의 값처럼 사용할 수 있다.

결론적으로 공용체를 사용하게 되면 동일 한 비트의 나열임에도 불구하고 다른 방식으로 꺼내볼 수 있는 것이다. 그래서 convert.pixel.blue라고 하면 해당 비트의 나열에서 마지막 5비트만 반환하는 것이다.


비트 필드는 보이는 것만큼 효율적일까?

비트 필드를 사용하면 공간도 절약할 수 있고 비트 단위의 논리 연산도 간단하게 수행하는 것처럼 보이지만 실제로는 생각하는 것 만큼 단순하지 않다.

단순히 convert.pixel.blue라고만 써주면 되지만 컴퓨터 내부적으로는 기존에 하던 작업을 고스란히 하고 있다. 다시 말해 여전히 비트 단위 논리 연산을 사용해서 동일한 작업을 하고 있는 것이다.

그렇기 때문에 비트 필드를 사용하는 것이 비트 단위 논리 연산자를 사용하는 것보다 빠르지 않다. 뿐만 아니라 메모리를 절약하기 위해서 비트 필드를 사용하지만, 비트 필드를 다루기 위해서 컴퓨터가 만들어낸 코드는 더욱 길어지게 된다. 
즉, 보관하는 데이터들은 더 적은 메모리를 차지하지만, 코드들은 더 많은 메모리를 차지하게 되는 셈이다.

Comments