C 언어에서의 유니언: 초보자 가이드

안녕하세요, 야심 찬 프로그래머 여러분! 오늘 우리는 C 프로그래밍의 흥미로운 세계로의 여행을 떠나게 될 것입니다. 특히 "유니언"이라는 작은 개념에 대해 집중적으로 배우겠습니다. 이전에 들어본 적 없으신분이라도 걱정 마세요 - 이 튜토리얼이 끝나면 유니언 마스터가 될 것입니다!

C - Unions

C 언어에서의 유니언은 무엇인가요?

기본적인 것부터 설명해 보겠습니다. 마법의 상자가 있다고 상상해 보세요. 이 상자는 다양한 종류의 물건을 보관할 수 있지만, 한 번에 하나의 물건만 보관할 수 있습니다. 이것이 바로 C 프로그래밍에서의 유니언입니다! 유니언은 동일한 메모리 위치에 다양한 데이터 타입을 저장할 수 있는 특별한 데이터 타입입니다.

이제 "그러면 왜 그런 걸 하고 싶을까?"라고 생각할 수도 있습니다. 그러나, 마음쓰는 친구여, 유니언은 메모리 절약이 필요하거나 동일한 메모리 위치를 다양한 목적으로 사용해야 할 때 매우 유용합니다.

유니언 정의하기

유니언을 정의하는 것은 매우 간단합니다. 구조체를 정의하는 것과 비슷하지만, struct 대신 union 키워드를 사용합니다. 다음은 간단한 예제입니다:

union MyUnion {
int integer;
float floating_point;
char character;
};

이 예제에서 우리는 MyUnion이라는 유니언을 정의했으며, 이 유니언은 정수, 부동소수점 수, 문자 중 하나를 저장할 수 있습니다. 마법의 상자 비유를 다시 떠올려보세요. 이 유니언은 한 번에 숫자, 소수점, 문자 중 하나를 보관할 수 있는 상자입니다!

유니언 멤버 접근하기

유니언 멤버에 접근하는 것은 쉽습니다! 구조체와 마찬가지로 점(.) 표기법을 사용합니다. 다음은 그 방법입니다:

union MyUnion u;
u.integer = 42;
printf("정수 값은: %d\n", u.integer);

u.floating_point = 3.14;
printf("부동소수점 값은: %f\n", u.floating_point);

u.character = 'A';
printf("문자 값은: %c\n", u.character);

이 예제에서 우리는 유니언에 다양한 타입의 데이터를 저장하고 출력합니다. 하지만 주의할 점이 있습니다. 유니언 멤버에 새로운 값을 할당할 때 이전 값이 덮어씌워집니다. 따라서, 우리 예제에서 u.character에 'A'를 할당한 후, 이전의 정수와 부동소수점 값은 더 이상 접근할 수 없습니다.

유니언 멤버 초기화하기

유니언을 초기화하는 것은 구조체를 초기화하는 것과 비슷하지만, 중요한 차이가 하나 있습니다: 한 번에 하나의 멤버만 초기화할 수 있습니다. 다음은 예제입니다:

union MyUnion u = {42};  // 정수 멤버 초기화
// OR
union MyUnion u = {.floating_point = 3.14};  // 부동소수점 멤버 초기화
// OR
union MyUnion u = {.character = 'A'};  // 문자 멤버 초기화

어떤 멤버를 초기화하든, 그 멤버만이 초기화됩니다.

유니언의 예제

practical한 예제를 보겠습니다. 회사의 다양한 종류의 직원을 관리하는 프로그램을 만들고 있다고 상상해 보세요:

#include <stdio.h>
#include <string.h>

union EmployeeID {
int number;
char string[20];
};

struct Employee {
char name[50];
union EmployeeID id;
int id_type;  // 0이면 숫자, 1이면 문자열
};

int main() {
struct Employee emp1, emp2;

strcpy(emp1.name, "John Doe");
emp1.id.number = 12345;
emp1.id_type = 0;

strcpy(emp2.name, "Jane Smith");
strcpy(emp2.id.string, "ABC-XYZ");
emp2.id_type = 1;

printf("직원 1: %s, ID: %d\n", emp1.name, emp1.id.number);
printf("직원 2: %s, ID: %s\n", emp2.name, emp2.id.string);

return 0;
}

이 예제에서 우리는 각 직원에 대해 숫자 ID 또는 문자열 ID를 저장할 수 있는 유니언을 사용하고 있습니다. Employee 구조체의 id_type 필드는 우리가 어떤 종류의 ID를 다루고 있는지 알려줍니다.

유니언의 크기

유니언의 흥미로운 사실 하나를 소개해 드리겠습니다: 유니언의 크기는 가장 큰 멤버에 의해 결정됩니다. 다음은 예제입니다:

#include <stdio.h>

union SizeTest {
int i;
float f;
char c;
};

int main() {
union SizeTest st;
printf("유니언의 크기: %lu 바이트\n", sizeof(st));
printf("정수의 크기: %lu 바이트\n", sizeof(int));
printf("부동소수점의 크기: %lu 바이트\n", sizeof(float));
printf("문자의 크기: %lu 바이트\n", sizeof(char));
return 0;
}

이 프로그램을 실행하면, 유니언의 크기가 가장 큰 멤버의 크기와 같다는 것을 확인할 수 있습니다.

구조체와 유니언의 차이

이제 "그렇다면 구조체와 무엇이 다른가요?"라고 궁금할 수 있습니다. 훌륭한 질문입니다! 차이점을 간단히 정리해 보겠습니다:

특징 구조체 유니언
메모리 할당 모든 멤버에 대해 메모리 할당 가장 큰 멤버에 대해 메모리 할당
멤버 접근 모든 멤버를 동시에 접근 가능 한 번에 하나의 멤버만 접근 가능
메모리 사용 더 많은 메모리 사용 적은 메모리 사용
데이터 저장 동시에 여러 값을 저장 가능 한 번에 하나의 값을 저장 가능
초기화 모든 멤버를 동시에 초기화 가능 한 번에 하나의 멤버만 초기화 가능

본질적으로, 구조체는 여러 상자를 붙여놓은 것처럼 보이고, 유니언은 한 번에 하나의 상자를 사용할 수 있는 것입니다.

그리고 이제, 여러분은 C 언어에서의 유니언에 대해 첫 걸음을 뗐습니다. 연습이 왕이라고 말하지만, 이 개념을 실험해 보세요. 누가 알겠는가? 유니언을 사용해 다음 큰 소프트웨어 혁신을 만들 수도 있을 것입니다!

행복한 코딩을 하고, 유니언과 함께 하세요! ?

Credits: Image by storyset