✅ union이란?
union은 여러 멤버가 동일한 메모리 공간을 공유하는 사용자 정의 자료형이다.
구조체와 문법은 유사하지만, 메모리 사용 방식이 다르다.
📦 메모리 구조
union Data {
int i;
float f;
char c;
};
- 위 예제에서 i, f, c는 모두 같은 메모리 공간을 공유한다.
- 즉, 한 번에 하나의 값만 저장할 수 있으며, 하나의 멤버에 값을 쓰면 나머지 멤버의 값은 덮어씌워져 손상된다.
🔹 메모리 사용 예시 (32비트 시스템)
union Data {
int i; // 4 byte
float f; // 4 byte
char c; // 1 byte
};
- union의 전체 크기: 가장 큰 멤버의 크기 → 4byte
멤버 |
공유 메모리 영역 (4바이트) |
i |
[0~3] (int로 해석) |
f |
[0~3] (float로 해석) |
c |
[0] (첫 1바이트만 사용) |
🔁 해석 방식의 차이
union Data {
int i;
float f;
};
union Data d;
d.i = 1065353216; // 이진수로는 0x3F800000
printf("%f\n", d.f); // 👉 1.0 (float로 해석됨)
- int로 저장된 값을 float로 해석 → bit-level reinterpretation
- 이것이 유니온의 핵심 기능 중 하나: 같은 데이터를 여러 방식으로 해석 가능
✅ union vs struct 비교
항목 |
struct |
union |
메모리 |
멤버별로 따로 공간 할당 |
모든 멤버가 하나의 공간을 공유 |
전체 크기 |
모든 멤버 크기의 합 (+패딩) |
가장 큰 멤버의 크기 |
동시 저장 |
모든 멤버에 값 유지 가능 |
하나의 멤버 값만 유지 가능 |
용도 |
다양한 필드를 함께 다루는 경우 |
여러 타입 중 하나만 사용하는 경우 |
🎯 활용 사례
1. 메모리 절약 (RAM 민감한 임베디드 환경 등)
union SensorData {
int temperature;
float humidity;
};
- 하나의 센서 타입만 활성화되므로 동시에 저장할 필요 없음 → 구조체보다 메모리 절약 가능
2. 다양한 타입의 해석 (타입 캐스팅 없이)
union {
int i;
float f;
} data;
data.f = 3.14;
printf("%d\n", data.i); // 3.14의 float 비트를 int로 출력
3. 비트 필드와 결합한 플래그 활용
union Flag {
struct {
unsigned int a : 1;
unsigned int b : 1;
} bits;
unsigned int all;
};
- 개별 비트 접근: flag.bits.a
- 전체 플래그 접근: flag.all
⚠️ 주의할 점
- 가장 마지막에 저장한 멤버만 유효한 값으로 간주해야 함
- 타입에 맞지 않게 해석하면 의미 없는 값이 나옴
- 구조체처럼 동시에 멤버를 활용하면 예상치 못한 결과 발생
✅ sizeof로 확인해 보기
union U {
char c;
int i;
double d;
};
printf("sizeof(U): %zu\n", sizeof(union U)); // double의 크기 (보통 8바이트)
union의 크기는 항상 가장 큰 멤버의 크기
🧠 핵심 요약
특성 |
설명 |
메모리 공유 |
모든 멤버가 하나의 메모리 공간을 공유 |
동시에 값 저장 불가 |
하나의 값만 유지 가능 |
해석 방식 |
저장된 데이터를 다른 타입으로 해석 가능 |
활용 |
메모리 절약, 다양한 타입 해석, 비트 플래그 구현 등 |
위험 |
잘못된 멤버 접근 시 의미 없는 값이 나올 수 있음 |