Union (유니온)은 같은 메모리 영역에 여러 값을 저장하는 특별한 데이터 유형입니다. union의 모든 구성원은 메모리에서 동일한 주소에 위치하며, 메모리의 크기는 가장 큰 구성원의 크기와 같습니다.
사용법:
예제:
union Data { int i; float f; char s[4]; }; union Data d; d.i = 0x41424344; // 이제 메모리에는 int, float, 문자열로 읽을 수 있는 4 바이트가 존재합니다 printf("%c%c%c\n", d.s[0], d.s[1], d.s[2]); // 벤더 특화 출력
함정 및 사용 규칙:
질문: 여러 필드를 가진 구조체를 사용할 수 있을 때 union을 사용할 의미는 무엇입니까?
답변: union의 사용은 메모리를 절약하는데, 왜냐하면 어떤 순간에 내부에 저장되는 것은 오직 하나의 값뿐이기 때문입니다. 구조체는 각 필드마다 메모리를 할당하지만, union은 가장 큰 필드에 대해서만 메모리를 할당하고 나머지는 그 메모리를 "공유"합니다. 또한 union은 동일한 메모리 조각 내에서 다양한 데이터 표현 간의 안전하거나 의도적인 변환을 수행할 수 있습니다.
예제:
struct S { int i; float f; } s; // sizeof = sizeof(int) + sizeof(float) union U { int i; float f; } u; // sizeof = max(sizeof(int),sizeof(float))
역사
장치 드라이버 프로젝트에서 "하드웨어"와의 연결은 비트 접근을 통해 union을 사용했습니다. 작은 리팩토링 후, 개발자는 union 내의 잘못된 필드에 데이터를 쓰기 시작했으며, 이로 인해 비실행 데이터가 읽혀지고 시스템에 치명적인 오류가 발생했습니다. 사용 중인 union은 매 순간 단 하나의 필드만 "진짜"입니다.
역사
union을 통해 메모리 관리를 한다는 네트워크 패킷 교환 중, 개발자는 구조체 정렬을 고려하지 않았습니다. 이로 인해 한 바이트가 이동했고, 구조체는 잘못된 오프셋으로 구문 분석되었으며, 프로토콜은 원본과 호환되지 않았습니다.
역사
직렬화 라이브러리 작업 중 개발자는 union을 값으로 함수에 전달했으나, 읽기 전 필요한 필드를 초기화하지 않았습니다. 이로 인해 데이터가 올바르게 직렬화되지 않았고, 출력 스트림에 쓰레기 데이터가 발생하여 원래 정보를 복원할 수 없게 되었습니다.