사용자 정의형이란, 기본 자료형 이외에 사용자가 직접 정의하는 데이터 형을 말해요.
배열
구조체
공용체
열거형
등이 사용자 정의형에 해당해요.
union
키워드를 사용해 선언하는 공용체는 구조체와 비슷한 구문 형식을 가지지만, 공용체 내의 모든 멤버들이 같은 기억장소를 공유해요.
union price
{
int won;
float dollar;
}
price는 이 공용체의 이름이고, won과 dollar는 이 공용체의 멤버가 돼요. struct로 선언하던 구조체와 구조가 비슷하죠?
|union price | type |
| :--- | :--- |
| .won | int |
| .dollar | float |
공용체 변수의 선언 방법도 구조체와 같아요.
union price a, b; // a, b를 메모리에 할당
공용체의 멤버 접근 방법은 구조체의 멤버 접근 방법과 동일해요.
a.won = 10;
b.dollar = 5.5;
구조체와 마찬가지로, typedef를 사용할 수 있어요.
typedef union price
{
int won;
float dollar;
} Price;
Price p = {.won = 10000};
printf("p : %d 원\n", p.won);
p.dollar = 7;
printf("p : $ %.2f\n", p.dollar);
🖥️실행결과
p : 10000 원 p : $ 7.00
공용체는 구조체의 멤버로 주로 사용해요. 구조체가 공용체를 멤버로 가질 때, 추가적인 멤버를 하나 더 정의해 이 공용체를 어떻게 해석할지 저장해요.
#define WON 0
#define DOLLAR 1
typedef union price
{
int won;
float dollar;
} Price;
typedef struct product
{
char *name;
_Bool won_or_dollar;
Price price;
} Product;
Product products[] = {
{"아이폰 14 Pro Max", DOLLAR, {.dollar = 1099.0}},
{"갤럭시 Z플립 4", WON, {.won = 1095000}}
};
for (int i = 0; i < 2; i++)
{
printf("제품명 : %s\n", products[i].name);
if (products[i].won_or_dollar)
printf("가격 : $ %.2f\n", products[i].price.dollar);
else
printf("가격 : %d 원\n", products[i].price.won);
}
🖥️ 실행결과
제품명 : 아이폰 14 Pro Max 가격 : $ 1099.00 제품명 : 갤럭시 Z플립 4 가격 : 1095000 원
열거형은 일부 숫자에 이름을 붙여 사용하고자 할때 사용할 수 있어요. 몇몇 대표적인 예시로, HTTP 상태 코드 같은 것들을 열거형으로 만들 수 있어요. 사람은 숫자보다는 단어에 더 익숙하기 때문에, 404로 쓰는것보단 NOT_FOUND라는 이름을 주는 편이 더 기억하기 쉬워요.
열거형은 enum
키워드를 사용해 선언할 수 있어요. 열거형은 유한 집합을 만들고, 그 집합의 원소로 식별자를 선언하는 수단을 제공해요. 쉽게 설명하면 특정한 정수 값들에 이름을 주고, 이들을 한개의 집단으로 묶어서 표현하는거에요. 아래 예시의 경우, 일주일의 각 요일의 이름들을 0~6에 해당하는 정수값들에 주고, 이들을 day라는 집단으로 분류했어요.
enum day {SUN, MON, TUE, WED, THU, FRI, SAT};
위 구문은 enum day
형을 정의하는 구문이에요. 각 단어들을 살펴볼게요.
단어 | 뜻 / 기능 |
---|---|
enum | 열거형을 선언해요 |
day | 열거형의 이름이에요 |
SUN, MON, ..., SAT | day에 속하는 열거자들이에요. |
열거형의 열거자는 정수처럼 사용할 수 있어요. (출력 서식문자로 %d를 쓴다던가...)
enum day {SUN, MON, TUE, WED, THU, FRI, SAT};
printf("%d\n", SUN); // 0 출력됨.
열거자의 값은 기본적으로 첫 번째 원소가 0이고, 이후 원소들은 이전 원소의 값보다 1 큰 값을 가져요. 위 예시의 경우, SUN은 0이고, MON은 1이고, ..., SAT은 6이에요.
열거자를 임의로 다른 값으로 초기화 할 수 있어요. 이 때, 초기화할 값을 주지 않은 열거자들은 앞 열거자의 값보다 1 큰 값을 가져요.
enum month {Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
// Jan = 1, Feb = 2, Mar = 3, ..., Dec = 12
eunm http_code {OK = 200, BAD_REQUEST = 400, UNAUTHORIZED, FORBIDDEN = 403, NOT_FOUND};
// OK = 200, BAD_REQUEST = 400, UNAUTHORIZED = 401, FORBIDDEN = 403, NOT_FOUND = 404
열거형 변수는 아래와 같이 선언할 수 있어요.
1. 이미 정의된 열거형으로 선언하기
enum day {SUN, MON, TUE, WED, THU, FRI, SAT};
enum day d1, d2;
enum day {SUN, MON, TUE, WED, THU, FRI, SAT} d1, d2;
enum {SUN, MON, TUE, WED, THU, FRI, SAT} d1, d2;
열거형 변수는 일반 변수와 같이 사용돼요.
d1 = MON;
if (d1 == d2)
printf("같은 날이에요!\n");
앞서 선언한 day 열거형을 사용해, 오늘이 무슨 요일인지 계산하는 예제를 만들어볼게요.
#include <stdio.h>
typedef enum day {SUN, MON, TUE, WED, THU, FRI, SAT} Day;
const day2sec = 60 * 60 * 24 // 24시간을 초로 환산해요.
int main(void)
{
time_t now;
Day today;
now = time(NULL); // 1970년 1월 1일 (목요일) 부터 흐른 시간을 초로 계산해요.
today = (now / day2sec + 4) % 7;
switch(today)
{
case SUN:
printf("오늘은 일요일이에요.\n");
break;
case MON:
printf("오늘은 월요일이에요.\n");
break;
// ...중략
default:
printf("시간이 잘못 계산되었습니다.\n);
break;
}
return 0;
}
배운 내용들을 정리해보고 있어요. 잘못 기재된 내용이 있다면, 댓글로 지적해주시면 수정할게요.