[C언어] C언어 구조체, 공용체, 열거형 - C언어 핵심 개념 정리
11장 구조체, 공용체, 열거형 - C언어 핵심 개념 정리
이번 장에서는 C언어에서 데이터의 집합을 다루는 중요한 개념인 구조체(struct), 공용체(union), 그리고 열거형(enum)에 대해 자세히 살펴보겠습니다. 이들은 복잡한 데이터를 깔끔하게 관리하고, 코드의 가독성 및 유지보수성을 크게 향상하는 중요한 도구입니다.
1. 기초 자료형과 파생 자료형
C언어 기본 자료형에는 int
, double
, char
등이 있습니다. 이들을 바탕으로 만든 파생 자료형이 바로 배열
, 포인터
, 구조체
, 그리고 공용체
입니다.
- 배열(array) : 같은 타입 변수들의 묶음
- 구조체(struct) : 서로 다른 타입 변수들의 묶음
2. 구조체 (struct)
구조체는 여러 변수들을 한데 묶어 하나의 복합 자료형을 만드는 방법입니다. 각 변수는 멤버라고 부릅니다. 구조체는 복잡한 데이터 집합을 하나의 이름으로 다룰 수 있어 편리합니다.
struct student {
int number;
char name[10];
double grade;
struct data dob; // 구조체 안에 구조체도 가능
float grades[5]; // 구조체 내 배열도 가능
};
구조체 변수 초기화 예시:
struct student s1 = {24, "KIM", 4.3};
구조체 멤버 참조:
s1.number = 24;
printf("학번: %d\n", s1.number);
- 구조체 변수끼리
==
비교는 불가능하지만, 대입(=
)과 주소 연산(&
)은 가능합니다. - 구조체 배열도 선언할 수 있습니다:
struct student list[100];
- 나중에 초기화는 캐스팅 문법으로:
s [0] = (struct student){"홍길동", 3};
구조체를 함수에 전달하기
구조체를 함수 인자로 전달하면 복사본이 전달되어 비효율적일 수 있으므로 보통 구조체 포인터를 사용합니다.
int equal(struct student* p1, struct student* p2) {
// 두 학생 비교 함수 예시
}
struct student a, b;
equal(&a, &b); // 주소를 넘겨 포인터로 전달
구조체 포인터 멤버 참조
포인터를 통해 구조체 멤버를 참조할 때는 아래 두 가지 방식 중 하나를 씁니다:
(*p). number
(포인터 역참조 후 멤버 접근)p->number
(화살표 연산자 사용, 더 간편)
예시:
struct student s = {24, "Kim", 4.3};
struct student *p = &s;
printf("학번=%d 이름=%s 성적=%.2f\n", p->number, p->name, p->grade);
3. 공용체 (union)
공용체는 여러 변수가 동일한 메모리 공간을 공유하는 특별한 자료형입니다. 즉, 여러 멤버가 겹치는 메모리 영역을 가지므로 한 번에 한 멤버만 유효한 값을 가질 수 있습니다.
구조체와 메모리 사용 비교:
- 구조체는 각 멤버마다 공간이 할당되어 총크기는 모든 멤버 크기의 합
- 공용체는 가장 큰 멤버 크기만큼 공간을 차지
union student {
int number;
char name[12];
};
union student s;
공용체 초기화는 구조체보다 조금 까다로울 수 있으니 주의가 필요합니다.
4. 열거형 (enum)
열거형은 관련된 상수들을 의미 있는 이름으로 묶어 가독성과 유지보수를 쉽게 도와줍니다. 기본적으로 정수 상수 집합으로 컴파일러가 자동으로 값을 할당합니다.
enum season {
SPRING, // 0
SUMMER, // 1
FALL, // 2
WINTER // 3
};
enum season s = FALL;
switch(s) {
case SPRING:
// 봄 처리
break;
case SUMMER:
// 여름 처리
break;
// ...
}
열거형의 장점:
- 가독성 향상
- 유지보수 용이
- 타입 안정성
- 중복 정의 방지
- 코드 간결성
5. typedef - 새로운 자료형 정의
typedef
는 기존 자료형에 새로운 이름을 붙이는 기능입니다. 긴 구조체 이름이나 복잡한 타입을 간단하게 만들 때 매우 유용합니다.
typedef unsigned char BYTE;
struct point {
int x;
int y;
};
typedef struct point POINT;
POINT a, b; // POINT는 struct point의 별칭
a.x = 10;
b.y = 20;
#define
과 비교:
#define UINT32 unsigned int
와 같이 간단한 타입 치환 가능- 배열 타입 등 복잡한 타입은
typedef
가 더 유용
마무리 및 팁
- 문자열은 매우 예민하기 때문에 대입으로 값 바꾸는 건 피하세요.
strcpy
를 활용하는 게 좋습니다. - 구조체와 공용체의 초기화 방식이 다르므로 주의해야 합니다. 공용체는 더 까다롭습니다.
- 구조체는 함수 인자 전달 시 복사 비용이 크니 가능하면 포인터를 사용하세요.
참고: 구조체, 공용체, 열거형을 적절히 활용하면 복잡한 데이터를 깔끔하고 효율적으로 다룰 수 있어 C언어 프로그래밍에서 매우 중요한 개념입니다. 이해가 쉽지 않더라도 예제 코드를 직접 작성하며 실습하는 걸 추천합니다.