Search
Duplicate
🏷️

Tagged Union

간단소개
C의 union에 대해 간단히 알아보자
팔만코딩경 컨트리뷰터
ContributorNotionAccount
주제 / 분류
C
Scrap
태그
union
9 more properties

C의 union

union은 struct와 문법이 거의 비슷하다.
typedef struct s_my_struct { int foo; float bar; } t_my_struct; typedef union u_my_union { int foo; float bar; } t_my_union;
C
복사
struct와 union 예시
struct는 모든 멤버를 포함하는 데 반해 union은 멤버 중 하나만 포함한다.
위 예시에서 struct는 foo와 bar를 각각 저장할 수 있는데, union은 둘 중 하나만 저장할 수 있다.
그 이유는 union의 모든 멤버는 같은 메모리 공간을 공유하기 때문이다.
struct는 모든 멤버 크기를 합한 만큼 공간을 차지하는 데 반해, union은 제일 큰 멤버만큼만 차지한다.

Union의 사용처

union만 갖고 할 수 있는 것은 그다지 많지 않아 보인다.
t_my_union 타입의 변수가 있어도, 이게 foo를 담고 있는지 bar를 담고 있는지 모르기 때문이다.

같은 데이터에 대한 다른 표현

예를 들면 같은 색상 데이터를 색상 코드나 byte 배열, 또는 구조체로 나타낼 수 있겠다.
typedef struct s_s_color { uint8_t alpha; uint8_t red; uint8_t green; uint8_t blue; } t_s_color; typedef union u_color { uint32_t code; uint8_t array[4]; t_s_color argb; } t_color;
C
복사
색상을 union으로 표현한 예시
하지만 이 예시에는 큰 결함이 있는데, 바로 엔디언이다.
0xFF440088에서 FF가 과연 alpha에 들어갈까? 리틀 엔디언에서는 blue에 들어갈 것이다.

reinterpret_cast

float u32_to_float(uint32_t u) { union s_u32_or_float { uint32_t u; float f; } a; a.u = u; return (a.f); }
C
복사
uint32_t를 받아 같은 비트열을 가진 float을 반환하는 함수 예시
uint32_tfloat이 모두 32비트라는 것을 알고 있으므로 uint32_t를 받아 그와 같은 비트열로 이루어진 float으로 바꾸거나, 그 역이 가능하다.
하지만 이는 union을 사용하지 않고도 가능하다.
float float_to_u32(float f) { return (*((uint32_t *)&f)); }
C
복사

선택적 변수

void print(t_my_union u, bool is_foo) { if (is_foo) printf("%d\n", u.foo); else printf("%f\n", u.bar); }
C
복사
union 사용 예시
어떤 조건에 따라 어떤 멤버로 사용해야 할지 결정될 때가 있다. 사실 거의 항상 그렇다.
그런 경우 union과 함께 그 union을 어떻게 해석해야 할지, 그 타입 정보를 같이 전달할 수 있다.
하지만 이렇게 쓸 거라면 union과 타입 정보를 같이 전달하는 것이 낫지 않을까?

Tagged Union

그래서 등장한 것이 tagged union이다.
union과 그 union을 어떤 멤버로 해석해야 할지를 저장하는 enum을 한데 묶은 것이다.
typedef enum e_my_union_type { MY_UNION_TYPE_A, MY_UNION_TYPE_B, MY_UNION_TYPE_C, } t_my_union_type; // t_my_type_a, t_my_type_b, t_my_type_c typedef union u_my_union_value { t_my_type_a a; t_my_type_b b; t_my_type_c c; } t_my_union_value; typedef struct s_my_union { t_my_union_type type; t_my_union_value value; } t_my_union;
C
복사
union과 type을 struct로 묶은 tagged union 예시
typedef enum e_my_union_type { MY_UNION_TYPE_A, MY_UNION_TYPE_B, MY_UNION_TYPE_C, } t_my_union_type; typedef struct s_my_union_a { t_my_union_type type; // ... a } a; typedef struct s_my_union_b { t_my_union_type type; // ... b } b; typedef struct s_my_union_c { t_my_union_type type; // ... c } c; typedef union u_my_union { t_my_union_type type; t_my_union_a a; t_my_union_b b; t_my_union_c c; } t_my_union;
C
복사
type으로 시작하는 struct를 union으로 묶은 tagged union 예시
위 예시를 포함해 여러가지 유형으로 나타날 수 있는데, 이들 모두 tagged union이다.