[C]공용체(Union)


이번 포스트는 공용체(Union)에 관한 내용입니다.


1️⃣ 공용체(union)

  • 공용체 안에 있는 여러 변수들이 같은 메모리를 공유합니다.
  • 즉, 똑같은 메모리 위치를 다른 변수들이 접근이 가능합니다.

(1) 공용체(union)로 구현한 비트 플래그

  • 공용체(union)의 요소로 비트 플래그 구조체동일의 크기의 자료형인 unsigned char자료형으로 선언해 주었습니다. 이 두요소는 같은 메모리 주소를 공유할 것 입니다.
  • 다음과 같이 공용체(union)을 이용하여 비트 플래그를 구현하면 변수 bit_sum을 이용하여 전체 비트를 한번에 비교할 수 있게 됩니다.

< 비트 플래그 구현(공용체) >

typedef union
{
    unsigned char bit_sum;
    typedef struct
    {
        unsigned char b1 : 1;
        unsigned char b2 : 1;
        unsigned char b3 : 1;
        unsigned char b4 : 1;
        unsigned char b5 : 1;
        unsigned char b6 : 1;
        unsigned char b7 : 1;
        unsigned char b8 : 1;
    } bits;
} bitflag_t
int main(void)
{
    bitflag_t flags = { 0, };

    int bool_b1 = (flags.bits.b1 == 1);              // OK
    int compare_two = (flags.bits.b2 == flags.bits.b6); // Ok
    int compare_all_1 = (flags.bit_sum == 0xFF);       // ok
    int compare_all_2 = (flags.bit_sum == 0);         // ok
}

(2) 비트플래그(공용체)이용 예

< 반복문을 이용하여 8가지 조건의 결과를 출력하는 코드(단순화시킨 예) >

int main(void)
{
    bitflags_t flags = { 0, };
    /* 코드 단순화 */
    flags.bits.b1 = 1; // 첫번째 조건 참
    flags.bits.b2 = 1; // 첫번째 조건 참
    flags.bits.b3 = 0; // 첫번째 조건 거짓
    flags.bits.b4 = 1; // 첫번째 조건 참
    flags.bits.b5 = 0; // 첫번째 조건 거짓
    flags.bits.b6 = 1; // 첫번째 조건 참
    flags.bits.b7 = 1; // 첫번째 조건 참
    flags.bits.b8 = 0; // 첫번째 조건 거짓

    int cnt = 1;
    for (int i = 0; i < 8; i++)
    {
        if ((flags.bit_sum & cnt) == cnt)  // 비트연산자 '&'을 이용
            printf("%d번째조건은 참입니다.\n", i + 1);
        else
            printf("%d번째조건은 거짓입니다.\n", i + 1);
        cnt *= 2;
    } 
}
/*---출력---*/
1번째조건은 참입니다.
2번째조건은 참입니다.
3번째조건은 거짓입니다.
4번째조건은 참입니다.
5번째조건은 거짓입니다.
6번째조건은 참입니다.
7번째조건은 참입니다.
8번째조건은 거짓입니다.




2️⃣ 공용체의 사용(단순한 메모리 공유 코드)

  • 메모리를 절약하기 위해 공용체를 이용하여 한 메모리 공간을 공유하는 아주 간단한 예입니다.
  • 하지만 사용하기도 복잡하고 실수하기도 쉬운 사용방법입니다.
  • ‘이런식으로 사용할 수 있다’의 정도로 알아보면 될 것 같습니다.

< 메모리를 공유하는 기본자료형 공용체 선언 >

typedef union
{
    int i_value;
    double d_value;
    char c_value;
} value_t;

< 사용(main함수) >

int main(void)
{
    value_t sample1;
    value_t sample2;
    int i_result;
    double d_result;
    char c_result[3];

    /* Window운영체제에서 double자료형의 크기 */
    printf("size of double in Window is %d\n", sizeof(double));
    /* sample1과 sample2 공용체의 크기 */
    printf("sample1, sample2 size is %d\n", sizeof(sample1));
    sample1.i_value = 13;
    sample2.i_value = 56;
    i_result = sample1.i_value + sample2.i_value;

    sample1.d_value = 3.14;
    sample2.d_value = 12.55;
    d_result = sample1.d_value + sample2.d_value;

    sample1.c_value = 'H';
    sample2.c_value = 'I';
    c_result[0] = sample1.c_value;
    c_result[1] = sample2.c_value;
    c_result[2] = '\0';

    printf("int result : %d\n", i_result);
    printf("double result : %f\n", d_result);
    printf("char result : %s\n", c_result);
}
/*---출력---*/
size of double in Window is 8
sample1, sample2 size is 8
int result : 69
double result : 15.690000
char result : HI




3️⃣ 공용체의 사용(디지털에서의 색상 처리)


(1) RGBA

  • RGB빛의 삼원색으로 R은 빨간색(Red), G은 초록색(Green), B은 파란색(Blue)을 나타냅니다. A빛의 명암을 나타냅니다.
  • 디지털에서는 이산적인 값을 쓰게 되며, 정보량(비트)에 따라서 표현할 수 있는 색의 가지수가 달라지게 됩니다.
  • 색상에 사용되는 정보량은 색심도(color depth)라는 용어가 사용됩니다. 색심도의 크기는 과거부터 오늘날까지 기술이 발전함에 따라 점점 증가했으며 오늘날에는 24비트의 크기를 사용하고 있습니다.(16,777,216가지 색을 표현 가능)
  • 24비트빨간색(R), 초록색(G), 파란색(B)채널에 각각 8비트(1바이트)를 할당하게 됩니다.

(2) 공용체를 이용한 (24비트)색심도 구현

  • int(4바이트)의 크기로 공용체를 만들어서 24비트(3바이트)의 색심도와 8비트(바이트)크기의 명암(A)를 표현할 수 있도록 선언하였습니다.

< 36비트(명암8비트포함)색심도 구현 코드 >

typedef union
{
    unsigned int val;

    struct
    {
        unsigned char r;
        unsigned char g;
        unsigned char b;
        unsigned char a;
    } rgba;  
} color_t;

< 노란색을 출력하는 main함수 >

  • 노란색빛을 표현하기 위해 빨간색(R)초록색(G)의 채널을 최대(255 == 0xff)B은 파란색(Blue)채널을 최소(0 == 0x00)으로 설정했습니다.
    int main(void)
    {
      color_t yellow;
    
      yellow.rgba.r = 255;  // 0xff
      yellow.rgba.g = 255;  // 0xff
      yellow.rgba.b = 0;   // 0x00
      yellow.rgba.a = 255; // 0xff
      printf("yellow: 0x%08x(%3d, %3d, %3d, %3d)\n", 
      yellow.val, yellow.rgba.r, yellow.rgba.g, yellow.rgba.b, yellow.rgba.a);
    }
    
/*---출력---*/
yellow: 0xffff00ff(255, 255, 0, 255)




© 2021.02. by kirim

Powered by kkrim