[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)