Union declaration
유니온(union)은 저장 공간이 겹치는 멤버들의 시퀀스로 구성된 타입입니다(반면 구조체(struct)는 저장 공간이 순차적으로 할당되는 멤버들의 시퀀스로 구성된 타입입니다). 언제든지 최대 하나의 멤버 값만 유니온에 저장될 수 있습니다.
공용체의
타입 지정자
는 사용된 키워드를 제외하면
struct
타입 지정자와 동일합니다:
목차 |
구문
union
attr-spec-seq
(선택 사항)
name
(선택 사항)
{
struct-declaration-list
}
|
(1) | ||||||||
union
attr-spec-seq
(선택 사항)
name
|
(2) | ||||||||
| name | - | 정의 중인 union의 이름 |
| struct-declaration-list | - | 임의 개수의 변수 선언, bit-field 선언, 그리고 static assert 선언. 불완전한 타입의 멤버와 함수 타입의 멤버는 허용되지 않음. |
| attr-spec-seq | - |
(C23)
선택적
attributes
목록, union 타입에 적용되며,
(2)
형식이
;
로 끝나지 않는 경우(즉, 전방 선언이 아닌 경우) 허용되지 않음.
|
설명
공용체는 가장 큰 멤버를 보관하기에 충분한 크기로만 구성됩니다(추가적인 이름 없는 후행 패딩이 추가될 수도 있습니다). 다른 멤버들은 가장 큰 멤버의 일부로 동일한 바이트에 할당됩니다.
union에 대한 포인터는 각 멤버에 대한 포인터로 캐스트될 수 있습니다 (union에 비트 필드 멤버가 있는 경우, union에 대한 포인터는 비트 필드의 기본 타입에 대한 포인터로 캐스트될 수 있습니다). 마찬가지로, union의 어떤 멤버에 대한 포인터든 enclosing union에 대한 포인터로 캐스트될 수 있습니다.
|
union의 내용에 접근하는 데 사용된 멤버가 값을 저장하는 데 마지막으로 사용된 멤버와 동일하지 않은 경우, 저장되었던 값의 객체 표현은 새로운 타입의 객체 표현으로 재해석됩니다(이를 type punning 이라고 합니다). 새로운 타입의 크기가 마지막에 기록된 타입의 크기보다 큰 경우, 초과 바이트의 내용은 명시되지 않습니다(트랩 표현일 수 있음). C99 TC3(DR 283) 이전에는 이 동작은 정의되지 않았지만, 일반적으로 이러한 방식으로 구현되었습니다. |
(since C99) |
|
struct와 유사하게, 타입이 이름 없는 union인 union의 무명 멤버는 익명 union(anonymous union) 으로 알려져 있습니다. 익명 union의 모든 멤버는 자신들의 union 레이아웃을 유지하면서 둘러싸는 struct나 union의 멤버로 간주됩니다. 이는 둘러싸는 struct나 union 또한 익명인 경우 재귀적으로 적용됩니다. struct v { union // anonymous union { struct { int i, j; }; // anonymous structure struct { long k, l; } w; }; int m; } v1; v1.i = 2; // valid v1.k = 3; // invalid: inner structure is not anonymous v1.w.k = 5; // valid struct와 유사하게, 이름 있는 멤버(익명 중첩 struct나 union을 통해 얻은 멤버 포함) 없이 union이 정의되면 프로그램의 동작은 정의되지 않습니다. |
(since C11) |
키워드
참고 사항
구조체와 공용체의 초기화 규칙에 대해서는 struct initialization 을 참조하십시오.
예제
#include <assert.h> #include <stdint.h> #include <stdio.h> int main(void) { union S { uint32_t u32; uint16_t u16[2]; uint8_t u8; } s = {0x12345678}; // s.u32가 현재 활성 멤버입니다 printf("Union S has size %zu and holds %x\n", sizeof s, s.u32); s.u16[0] = 0x0011; // s.u16이 현재 활성 멤버입니다 // s.u32 또는 s.u8에서 읽는 것은 객체 표현을 재해석합니다 // printf("s.u8 is now %x\n", s.u8); // 지정되지 않음, 일반적으로 11 또는 00 // printf("s.u32 is now %x\n", s.u32); // 지정되지 않음, 일반적으로 12340011 또는 00115678 // union의 모든 멤버에 대한 포인터는 자신과 union과 비교 시 동일합니다 assert((uint8_t*)&s == &s.u8); // 이 union은 3바이트의 트레일링 패딩을 가집니다 union pad { char c[5]; // 5바이트 차지 float f; // 4바이트 차지, 4의 정렬을 부과 } p = { .f = 1.23 }; // float의 정렬을 충족하기 위해 크기는 8입니다 printf("size of union of char[5] and float is %zu\n", sizeof p); }
가능한 출력:
Union S has size 4 and holds 12345678 size of union of char[5] and float is 8
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| DR 499 | C11 | 익명 구조체/공용체의 멤버들이 포함하는 구조체/공용체의 멤버로 간주됨 | 해당 멤버들은 자신의 메모리 레이아웃을 유지함 |
참고문헌
- C23 표준 (ISO/IEC 9899:2024):
-
- 6.7.2.1 구조체 및 공용체 지정자 (p: TBD)
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.7.2.1 구조체 및 공용체 지정자 (p: 81-84)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.7.2.1 구조체 및 공용체 지정자 (p: 112-117)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.7.2.1 구조체 및 공용체 지정자 (p: 101-104)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.5.2.1 구조체 및 공용체 지정자
참고 항목
|
C++ 문서
for
Union 선언
|