Topic 3: 열거형과 공용체 🎭🔄
🎯 학습 목표
- 열거형(enum)의 개념과 사용법을 이해할 수 있다
- 공용체(union)의 메모리 절약 원리를 익힐 수 있다
- 실제 프로그램에서 enum과 union을 효과적으로 활용할 수 있다
- 타입 안전성과 가독성을 향상시키는 방법을 배울 수 있다
🌈 열거형(Enumeration)이란?
열거형은 서로 관련된 상수들을 하나로 묶어서 의미있는 이름을 부여하는 데이터 타입입니다.
마치 요일을 숫자로 표현하는 대신 “월요일”, “화요일”로 표현하는 것처럼, 코드를 더 읽기 쉽고 이해하기 쉽게 만들어줍니다! 📅
문제: 숫자의 의미를 알기 어려움
// ❌ 숫자로만 된 코드 - 의미를 알기 어려움
int playerState = 2; // 2가 뭘을 의미하죠?
int direction = 1; // 1은 어느 방향일까요?
if (playerState == 2) { // 2가 뭔지 기억해야 해요
cout << "공격 중!" << endl;
}
😟 문제점: 나중에 코드를 보면 숫자의 의미를 기억하기 어려워요!
🔤 열거형 기초 문법
간단한 열거형 예제
#include <iostream>
using namespace std;
// 게임 상태를 열거형으로 정의
enum PlayerState {
IDLE, // 0 - 대기
WALKING, // 1 - 걸어가기
ATTACKING, // 2 - 공격
DEAD // 3 - 죽음
};
enum Direction {
NORTH, SOUTH, EAST, WEST
};
int main() {
// 열거형 사용
PlayerState state = ATTACKING;
Direction dir = NORTH;
// 상태 확인
if (state == ATTACKING) {
cout << "공격 중입니다!" << endl;
}
// switch문으로 방향 처리
switch (dir) {
case NORTH:
cout << "북쪽으로 이동" << endl;
break;
case SOUTH:
cout << "남쪽으로 이동" << endl;
break;
case EAST:
cout << "동쪽으로 이동" << endl;
break;
case WEST:
cout << "서쪽으로 이동" << endl;
break;
}
return 0;
}
🎨 실전 예제: 색상 시스템
#include <iostream>
#include <string>
using namespace std;
// 색상 열거형
enum Color {
RED, // 0 - 빨강
GREEN, // 1 - 초록
BLUE, // 2 - 파랑
YELLOW // 3 - 노랑
};
// 색상을 문자열로 변환
string colorName(Color c) {
switch (c) {
case RED: return "빨강";
case GREEN: return "초록";
case BLUE: return "파랑";
case YELLOW: return "노랑";
default: return "알수없음";
}
}
int main() {
Color myColor = RED;
cout << "선택한 색상: " << colorName(myColor) << endl;
cout << "색상 번호: " << myColor << endl; // 0 출력
// 다른 색상들 연습
Color colors[] = {RED, GREEN, BLUE, YELLOW};
cout << "\n모든 색상:" << endl;
for (int i = 0; i < 4; i++) {
cout << (i+1) << ". " << colorName(colors[i]) << endl;
}
return 0;
}
💪 더 안전한 enum class
enum class란?
C++11부터 사용할 수 있는 더 안전한 열거형입니다.
// 기본 enum의 문제
enum Color1 { RED, GREEN, BLUE };
enum Status { RED, ACTIVE }; // ❌ RED가 중복!
// enum class 해결책
enum class Color2 { RED, GREEN, BLUE };
enum class Status2 { RED, ACTIVE }; // ✅ 충돌 없음!
int main() {
// 사용법
Color2 myColor = Color2::RED; // 범위 지정 필요
if (myColor == Color2::RED) {
cout << "빨간색입니다!" << endl;
}
return 0;
}
enum class의 장점:
- 이름 충돌 방지
- 더 안전한 코드
🔄 공용체(Union)란?
공용체는 동일한 메모리 공간을 여러 변수가 공유하는 데이터 타입입니다. 메모리를 절약하면서도 하나의 데이터를 여러 방식으로 해석할 수 있습니다.
간단한 공용체 예제
#include <iostream>
using namespace std;
union Data {
int intValue; // 4 bytes
float floatValue; // 4 bytes
char charArray[4]; // 4 bytes
// 모두 같은 메모리 공간을 공유!
};
int main() {
cout << "🔄 === 공용체 기본 개념 === 🔄" << endl;
Data data;
cout << "공용체 크기: " << sizeof(data) << " bytes" << endl; // 4 bytes
// 정수 값 저장
data.intValue = 0x41424344; // 16진수 값
cout << "\n정수 값 저장 후:" << endl;
cout << "intValue: " << data.intValue << endl;
cout << "floatValue: " << data.floatValue << endl;
cout << "문자 배열: ";
for (int i = 0; i < 4; i++) {
cout << "'" << data.charArray[i] << "' ";
}
cout << endl;
// 실수 값 저장 (같은 메모리 덮어씀)
data.floatValue = 3.14159f;
cout << "\n실수 값 저장 후:" << endl;
cout << "intValue: " << data.intValue << endl;
cout << "floatValue: " << data.floatValue << endl;
// 문자 배열 저장
data.charArray[0] = 'H';
data.charArray[1] = 'i';
data.charArray[2] = '!';
data.charArray[3] = '\0';
cout << "\n문자 배열 저장 후:" << endl;
cout << "intValue: " << data.intValue << endl;
cout << "문자 배열: " << data.charArray << endl;
return 0;
}
🎮 열거형과 공용체 활용: 게임 상태 관리
열거형으로 게임 상태 관리하기
게임에서 플레이어의 상태를 숫자로 관리한다면:
// ❌ 매직 넘버로 관리 (혼란스러움)
int playerState = 2; // 2가 뭔지 기억해야 함
if (playerState == 2) {
cout << "공격 중!" << endl;
}
열거형으로 깔끔하게 해결:
// ✅ 명확하고 이해하기 쉬움
enum class PlayerState {
IDLE, // 0: 대기
MOVING, // 1: 이동
ATTACKING,// 2: 공격
DEFENDING // 3: 방어
};
PlayerState state = PlayerState::ATTACKING;
if (state == PlayerState::ATTACKING) {
cout << "공격 중!" << endl; // 명확함!
}
공용체로 메모리 절약하기
게임에서 다양한 이벤트 데이터를 저장할 때:
// 이벤트 타입에 따라 다른 데이터가 필요
enum class EventType {
MOVE, ATTACK, HEAL
};
// 공용체 사용 전 (메모리 낭비)
struct Event_Before {
EventType type;
// 모든 가능한 데이터를 저장 (낭비!)
int moveX, moveY; // 이동용
int damage; // 공격용
int healAmount; // 치료용
}; // 큰 메모리 사용
// 공용체 사용 후 (메모리 절약)
union EventData {
struct { int x, y; } moveData; // 이동 데이터
int damage; // 공격 데이터
int healAmount; // 치료 데이터
}; // 가장 큰 멤버만큼의 메모리 사용
struct Event_After {
EventType type; // 어떤 데이터인지 구분
EventData data; // 실제 데이터
};
Tagged Union 패턴
핵심 아이디어: enum으로 타입을 표시하고, union으로 데이터를 저장
#include <iostream>
using namespace std;
enum class DataType { INT, FLOAT, CHAR };
union Data {
int intValue;
float floatValue;
char charValue;
};
struct SafeData {
DataType type; // 타입 표시 (Tag)
Data value; // 실제 데이터
};
void printData(const SafeData& data) {
switch (data.type) {
case DataType::INT:
cout << "정수: " << data.value.intValue << endl;
break;
case DataType::FLOAT:
cout << "실수: " << data.value.floatValue << endl;
break;
case DataType::CHAR:
cout << "문자: " << data.value.charValue << endl;
break;
}
}
int main() {
// 안전하게 사용하기
SafeData data1 = {DataType::INT, {42}};
SafeData data2 = {DataType::FLOAT, {3.14f}};
printData(data1);
printData(data2);
return 0;
}
🤔 언제 사용하면 좋을까?
열거형 사용 시기:
✅ 상태 관리: 게임 상태, 메뉴 상태, 연결 상태
✅ 옵션 선택: 난이도, 색상, 크기
✅ 에러 코드: 성공/실패 원인 구분
공용체 사용 시기:
✅ 메모리 절약: 한 번에 하나의 값만 필요할 때
✅ 데이터 해석: 같은 데이터를 다른 방식으로 보고 싶을 때
✅ 시스템 프로그래밍: 하드웨어 레지스터, 네트워크 패킷
실습: 간단한 계산기 상태
#include <iostream>
using namespace std;
enum class Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE };
union Number {
int intValue;
double doubleValue;
};
int main() {
// 여기에 코드를 작성하세요
// 1. Operation을 하나 선택하세요
// 2. 두 개의 Number를 만들어보세요
// 3. 선택한 연산을 수행해보세요
return 0;
}
언제 열거형을 사용할까요?
✅ 상태 관리: 게임 상태, 단계별 진행상황
✅ 선택 옵션: 난이도 선택, 색상 선택
✅ 에러 처리: 성공/실패 원인 구분
// 난이도 예제
enum GameLevel {
BEGINNER, INTERMEDIATE, EXPERT
};
GameLevel level = BEGINNER;
if (level == BEGINNER) {
cout << "초보자 모드 시작!" << endl;
}
직접 해보기! 📝
간단한 요일 확인 프로그램을 만들어보세요:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
};
int main() {
Day today = FRIDAY;
// 여기에 switch문을 사용해서
// 오늘이 주말인지 평일인지 확인해보세요
return 0;
}
💡 메모리 절약의 원리
struct Person {
int age; // 4 bytes
float salary; // 4 bytes
char grade; // 1 byte
// 총 9 bytes이지만 실제로는 12 bytes (패딩)
};
union PersonData {
int age; // 4 bytes
float salary; // 4 bytes
char grade; // 1 byte
// 실제 크기: 4 bytes (가장 큰 멤버 기준)
};
int main() {
cout << "구조체 크기: " << sizeof(Person) << " bytes" << endl;
cout << "공용체 크기: " << sizeof(PersonData) << " bytes" << endl;
cout << "\n공용체가 메모리를 절약합니다!" << endl;
return 0;
}
핵심: 공용체는 가장 큰 멤버의 크기만큼만 메모리를 사용합니다!
🧪 간단 퀴즈!
🤔 퀴즈 1: 열거형의 기본 값은?
enum Day { MONDAY, TUESDAY, WEDNESDAY };
cout << MONDAY << " " << TUESDAY << " " << WEDNESDAY;
정답: 0 1 2
열거형은 기본적으로 0부터 시작해서 1씩 증가합니다.
🤔 퀴즈 2: 공용체의 크기는?
union Test {
char c; // 1 byte
int i; // 4 bytes
};
정답: 4 bytes
공용체는 가장 큰 멤버의 크기와 같습니다. int가 4 bytes로 더 큽니다.
🎯 도전 과제
과제 1: 간단한 신호등 시스템
신호등의 상태(빨강, 노랑, 초록)를 enum으로 정의하고, 현재 신호에 따라 “정지”, “주의”, “통과” 메시지를 출력하는 프로그램을 만들어보세요.
과제 2: 학생 성적 등급
점수 범위에 따른 등급(A, B, C, D, F)을 enum으로 정의하고, 점수를 입력받아 해당 등급을 출력하는 프로그램을 작성해보세요.
🎉 마무리
열거형과 공용체는 C++에서 메모리를 효율적으로 사용하면서도 코드의 가독성을 높이는 강력한 도구입니다!
오늘 배운 내용:
- 🌈 열거형(enum)으로 의미있는 이름 사용하기
- 💪 enum class로 더 안전한 코드 만들기
- 🔄 공용체(union)의 메모리 공유 원리
- 🎯 switch문과 열거형 조합하기
다음 단계:
- Topic 4에서는 구조체들을 조합한 복합 자료구조를 학습합니다
- 실제 프로젝트에서 사용할 수 있는 데이터 구조 설계를 배울 예정입니다
이제 여러분은 데이터를 더 효율적이고 안전하게 관리할 수 있는 도구들을 익혔습니다! 💪