리메이크 중/C,C++ 이론 중심

C(&C++) 이론 15. 사용자 정의 자료형 2) 공용체

라이피 (Lypi) 2021. 6. 21. 00:00
반응형


내용 참고

YES C (정보공학연구소/생능출판사)

혼자 연구하는 C/C++ (Soen.kr/와우북스)

Microsoft Docs (구 MSDN)


C언어 이론 15 / 사용자 정의 자료형 2) 공용체

Ⅱ. 공용체

■ 공용체는 같은 메모리 공간을 공유하는 변수들을 묶어놓은 것이다.

ⅰ. 공용체의 선언

■ 공용체를 선언할 때는 'union' 키워드를 사용한다.

■ 공용체를 선언하는 방법은 구조체를 선언할 때와 완전히 동일하다. 

■ 즉, 4가지의 구조체 선언방법을 공용체에도 똑같이 적용할 수 있다.

 

 

■ 이렇게 선언한 공용체의 이름은 하나의 타입처럼 취급된다.


ⅱ. 공용체의 특징

1. 메모리를 공유한다.

■ 공용체의 가장 큰 특징은 멤버들끼리 같은 공간(=메모리)를 공유한다는 것이다.

■ 아래와 같은 상황에서 구조체는 적어도 멤버들의 크기를 모두 더한것보다 큰 크기를 갖는다. (아래의 경우 최소 13byte)

■ 하지만 공용체의 경우 가장 크기가 큰 멤버의 크기를 기준으로 크기를 갖는다. (아래의 경우 최소 8byte)

■ 다만 정확하게 메모리가 할당되는 것은 운영체제나 하드웨어에 따라 다를 수 있다. 

 

2. 값이 오염될 수 있다.

■ 멤버들끼리 같은 메모리를 공유한다는 것은 1번 멤버의 값을 바꾸면 2번 멤버의 값도 바뀐다는 뜻이다.

■ 즉, 공용체를 사용하면 메모리를 아낄 수는 있지만 값이 오염될 수 있다.

■ 그렇기 때문에 공용체는 매우 특수한 경우에만 사용된다.

 


ⅲ. 공용체의 초기화와 기본값 설정

■ 공용체는 멤버들간에 값을 공유하기 때문에 초기화할 때 값을 하나만 넣어야 한다.

■ 이는 기본값을 설정할 때도 마찬가지이다.


ⅳ. 공용체를 사용하는 경우

1. 메모리를 극도로 절약해야 할 때

■ 공존할 수 없거나, 공존할 필요가 없는 값들을 공용체로 묶어서 선언하면 메모리를 절약할 수 있다.

■ 하지만 메모리가 충분한 상황에서 억지로 공용체를 사용하는 것은 득보다는 실이 많기 때문에 추천되지 않는다.

2. 커다란 데이터를 쪼개서 확인할 필요가 있을 때

■ 예를 들어 1byte(=8bit)의 값을 1bit씩 쪼개서 확인하고 싶다면 다음과 같은 코드를 사용할 수 있다.

#include <iostream>

union data {
	struct bit {
		bool _0 : 1; // LSB
		bool _1 : 1;
		bool _2 : 1;
		bool _3 : 1;
		bool _4 : 1;
		bool _5 : 1;
		bool _6 : 1;
		bool _7 : 1; // MSB
	} d;
	char value;
};

int main(void) {
	data t;
	scanf("%d",(int*)(&t.value));
	printf("%d%d%d%d %d%d%d%d\n",
		t.d._7, t.d._6, t.d._5, t.d._4,
		t.d._3, t.d._2, t.d._1, t.d._0);

	return 0;
}

■ 위의 코드를 사용하면 0~255까지의 숫자를 이진수로 확인할 수 있다.

■ 참고로 출력을 _0부터가 아니라 _7부터 하고 있는데 이는 리틀 엔디안 방식을 사용하고 있는 경우를 가정한 것이다.

■ 빅 엔디안과 리틀 엔디안에 대한 자세한 설명은 추후에 다룰 예정이다.

3. 나눠진 데이터를 묶어서 다루고 싶을 때

■ 위와는 반대의 경우로 4개로 숫자로 이루어진 ip주소를 예로 들수 있다.

#include <stdio.h>

union tag_ip {
    unsigned char addr[4];
    unsigned long ip;
};

int main()
{
    tag_ip a;
    
    scanf("%d.%d.%d.%d",(int*)(&a.addr[0]),(int*)(&a.addr[1]),(int*)(&a.addr[2]),(int*)(&a.addr[3]));
    
    printf("ip : %ld \n", a.ip);
    printf("%d.%d.%d.%d",a.addr[0],a.addr[1],a.addr[2],a.addr[3]);

    return 0;
}

■ 입력 자체는 4개의 숫자를 따로 따로 받지만 실제 사용은 하나로 묶어서 사용하는 경우이다.


반응형