1. Home
  2. 프로그래밍 강좌/C
  3. [C언어 강좌] #15 공용체와 열거형

[C언어 강좌] #15 공용체와 열거형

안녕하세요 파일입니다.

저번 구조체편에 이어서 공용체와 열거형입니다.

 

구조체를 제대로 이해하셨다면 이번에 새로배우는 공용체는 구조체와 사용방법이 거의 동일하기 때문에

어렵지 않게 익힐 수 있습니다.

 

또한 열거형도 그렇게 어려운 내용은 아니니 걱정하지 않으셔도 됩니다.

그럼 바로 시작해봅시다.

 

 

공용체

앞에서 배운 구조체처럼 사용자 정의 자료형에는 또 '공용체' 라는것이 있습니다.

공용체는 선언 형태와 사용 형태가 구조체와 거의 동일합니다.

 

그럼 공용체는 무엇일까요?

공용체의 의미는 그룹으로 묶여진 여러 개의 멤버 변수들 중에 가장 큰 메모리 공간을 '공유' 해서 사용하는 것 입니다.

밑줄쳐진 저 공유한다는 부분이 구조체와의 매우 큰 차이점이라고 할 수 있겠습니다.

 

단순히 말로만은 이해가 어려으므로 그림을 이용해서 한번 구조체와 메모리 할당을 비교해보겠습니다.

 

struct date
{
	int i;
	char c;
	double d;
};

다음과 같은 구조체가 있습니다.

구조체의 경우는 메모리가 멤버 변수 각각 할당되므로 위 date의 메모리 크기는 4+1+8=13(byte) 입니다.

 

date 구조체를 그림으로 나타내면 다음과 같습니다.

 

 

다음으로 공용체의 메모리 할당입니다.

공용체의 선언방법을 따로 배우진 않았지만 일단 확인해 봅시다.

union date
{
	int i;
	char c;
	double d;
};

date 공용체를 다시 그림으로 나타내면 다음과 같습니다.

차이점이 보이시나요?

 

분명 구조체와 공용체의 차이를 벌써 눈치챈 분들도 있겠지만 하나씩 설명을 해보겠습니다.

 

우선 공용체를 선언하려면 'union' 이라는 키워드를 사용해야 합니다.

$cf$ union : 조합, 협회, 연방, 연합

 

공용체는 구조체와 선언(정의), 멤버 변수 선언, 멤버 변수 접근 방법 모두 구조체와 완전 동일하나

단순히 struct 키워드를 union 키워드로 바꿔주시기만 하면 됩니다.

 

그러나 구조체에서는 멤버 변수들이 각각 독립적인 메모리 공간을 갖게 되었던 반면

공용체에서는 멤버 변수들 중 가장 큰 메모리 공간을 차지하는 자료형의 크기로 메모리가 생성되고 이 메모리를 다른 변수들이 함께 공유해서 사용하게 됩니다.

 

이것이 핵심입니다.

바로 위 사진을 보시면 멤버 변수중에 가장 큰 표현범위를 지닌 자료형, double = 8byte의 크기를 공유하며 int i, char c가 메모리로 잡혀있습니다.

 

그림과 이론적인 부분은 이해했으므로 이제 실제로 소스코드를 작성해보겠습니다.

아래 예제를 통해서 구조체 변수의 크기와 공용체 변수의 크기를 각각 확인해보겠습니다.

 

#include <stdio.h>

union pos //공용체 정의 
{
	int x;
	int y;
};

struct student //구조체 정의 
{
	int x;
	int y;
};


int main(){
	printf("size of pos(union) : %d\nsize of student(struct) : %d", sizeof(union pos), sizeof(struct student));
	return 0;
}

size of pos(union) : 4
size of student(struct) : 8
--------------------------------
Process exited after 0.005131 seconds with return value 0
계속하려면 아무 키나 누르십시오 . . .

sizeof() 내장 함수를 이용해 크기를 출력해보면

공용체의 경우 4byte, 구조체의 경우 8byte가 출력되었습니다.

 

공용체 pos에서 int형 변수가 2개, 가장 큰 메모리 공간은 역시 4byte의 int 이므로

4바이트 내에서 메모리가 공유됩니다.

 

구조체 student는 int x, int y가 각각 4바이트씩 독립적인 메모리 공간을 가지게 되어 8byte가 출력됩니다.

 

공유를 하는건 알겠으나 공용체의 메모리는 정확히 어떻게 사용하는걸까요?

예제를 하나 더 봐보겠습니다.

 

#include <stdio.h>

union pos //공용체 정의 
{
	int x;
	int y;
};




int main(){
	union pos p; //공용체 변수 선언
	p.x = 10;
	
	printf("%d %d \n", p.x, p.y); 
	return 0;
}

main() 함수의 첫줄에서 공용체 변수 p를 선언했습니다.

구조체 변수와 동일하지만 union으로만 바꿔주시면 됩니다.

 

공용체의 멤버 변수들 중에 가장 큰 자료형이 int형이므로 4바이트의 메모리 공간이 할당됩니다.

(만약 구조체였다면 8바이트가 할당되었을 겁니다.)

 

접근연산자 .을 이용해 p.x에 10을 대입해 초기화 합니다.

p.x와 p.y를 출력해보았는데 p.x가 10이 출력될 뿐만 아니라 p.y도 10이 출력됩니다.

 

4바이트 메모리 공간을 공유해서 사용하고 있기 때문에 p.x의 값이 변경되면 p.y도 변경됩니다.

p.y의 값을 변경하면 마찬가지로 p.x도 변경됩니다. 공유하고 있기 때문입니다.

 

TMI

이 Union(공용체)라는 것을 사용하는 이유는 메모리가 부족할때 많이 사용했지만

요즘은 램은 기본 8GB, 16GB를 탑재하고 있기 때문에 사실 넘쳐나는게 현실입니다.

 

그래서 현시점에선 잘 사용되지 않습니다.

(물론 메모리가 한정되어 있는 임베디드 환경이나 묶어서 보내야 하는 패킷전송에서는 유용하게 사용할 수 있습니다.)

 

그래도 구조체와 거의 동일하고 메모리를 공유한다는 개념정도만 알면 학습할 수 있기에

개념을 알아두는것 정도는 나쁘지 않다고 생각합니다.

 

열거형

지금까지 사용자 정의 자료형으로 구조체와 공용체에 대해서 학습해보았습니다.

포인터편이 정말 고통의 연속이였지만 구조체와 공용체는 그래도 라이트하게 어렵지 않게 학습하셨을거라고 믿습니다.

 

마지막으로 열거형에 대해 알아보겠습니다.

열거형을 사용하면 변수가 갖는 갚에 의미를 부여할 수 있고 프로그램의 가독성을 높일 수 있습니다.

 

다음으로 열거형을 만드는 방법입니다.

다음과 같이 열거형을 선언시 컴파일러는 실제로 열거형 멤버들을 정수형 상수로 인식합니다.

 

사진처럼 enum 키워드를 이용하여 열거형을 선언하면 컴파일러는 실제로 열거형 멤버들을 정수형 상수로 인식하게 됩니다. 말로만 해선 잘 이해되지 않으니 아래 예제를 보면서 열거형을 사용하는 방법을 익혀보도록 합시다.

 

$cf$ enumeration : 목록

 

#include <stdio.h>

enum week {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; //열거형 정의 

int main(){
	enum week p1, p2, p3; //열거형 변수 선언
	
	p1 = Monday;
	p2 = Tuesday;
	p3 = Wednesday;
	
	printf("%d %d %d\n", Monday, Tuesday, Wednesday);
	printf("%d %d %d", p1, p2, p3);
	 
	return 0;
}

0 1 2
0 1 2
--------------------------------
Process exited after 0.004729 seconds with return value 0
계속하려면 아무 키나 누르십시오 . . .

3행에서 enum week을 통해 열거형을 정의하고 있습니다.

week 중괄호 나열된(열거된) 내부 변수들은 초기화 되지 않았기 때문에 0부터 1씩 올라가며 자동적으로 설정됩니다.

(Monday = 0, Tuesday = 1, Wednesday = 2 . . .)

 

또한 변수를 선언할때 자료형에 enum 키워드를 붙이면 열거형 변수를 선언할 수 있습니다.

이 열거형 변수들은 열거형 상수들에 접근할 수 있습니다. 

열거형 변수를 각각 만들어서 열거형 상수를 저장하고 출력하는 예제입니다.

 

위 예제처럼 열거형을 사용하면 상수값에 의미를 부여할 수 있고 (Monday = 0...) 프로그램의 가독성도 높일 수 있습니다.

 

추가적으로 Monday = 0 으로 0부터 인덱싱을 자동으로 해주는데 1부터 시작하게 하고 싶을때도 있습니다.

 

enum week {Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; //열거형 정의

그러면 이렇게 해주시면 됩니다. 이렇게 하게되면 Monday = 1, Tuesday = 2, Wednesday = 3 으로 1부터 시작하면서 초기화 됩니다.

 

enum week {Monday, Tuesday = 2, Wednesday, Thursday, Friday, Saturday, Sunday}; //열거형 정의

또한 이렇게 하면 Tuesday = 2, Wednesday = 3, Thursday = 4... 로 초기화가 됩니다.

그러면 제일처음 Monday는 ? 컴퓨터가 똑똑하게 1을 넣어서 맞춰줄까요.

그렇지 않습니다.

 

Monday에는 값이 지시된것이 없으며, 맨 앞의 것이고 따로 초기화 하지 않아서 자동으로 0이 들어가게 됩니다.

 

enum week {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday = 7, Sunday}; //열거형 정의

비슷한 것으로 이렇게 하게되면

0 1 2 3 4 7 8 이 출력되게 됩니다.

값을 따로 지정해주면 그 뒤에건 자동으로 그 값 + 1을 해서 들어가고

앞에 지정되지 않은것들은 0부터 세면서 들어갑니다.

 

Saturday에 7을 넣어줬다고 해서

2 3 4 5 6 7 8 처럼 되지 않는다 이말이죠.

 

enum을 많이 쓰다보면 알겠지만 글쓴이의 경우 이걸 몰라서 손코딩 시험때 점수가 깎인 기억이 있어서 이번에 기억해두고 있습니다 ㅜㅜ

 


이번 강의는 여기까지입니다!

주제가 2개였는데도 금방끝났네요.

 

포인터는 주제가 1개였는데 혼자 3편이 나왔는데..

 

다음편에선 문자열을 다루는 문자열 표준 함수와 기타 표준함수에 대해 알아보겠습니다!!

SNS 공유하기
네이버밴드
카카오톡
페이스북
X(트위터)

최근글
인기글
이모티콘창 닫기
울음
안녕
감사
당황
피폐