공용체란 C언어 문법 책 뒷쪽에, 구조체(structure) 다음에 꼽사리로 나오는 데이터 구조.
예를 들어, 아래와 같은 공용체가 정의되어있다고 하자.

typedef union _data {
    char a;
    int b;
    float c;
} data;


이 경우, 이 공용체는 전체 8바이트의 크기를 갖는다. 이 8바이트 중에서 첫 번째 바이트는 a 변수가 사용하고, 처음 네 개의 바이트는 b가 사용하고, 처음부터 끝까지 여덟 바이트는 c가 사용한다. 즉, 세 멤버 변수 a, b, c 는 중첩된 메모리 공간을 같이 사용한다. 그러므로, a 변수에 값을 저장하면, b와 c에 저장된 값은 전혀 다른 값으로 바뀌게 된다.

"도대체 이런 구조를 왜 써야할까???" 하는 의문을 바로 몇 달전 C 프로그래밍을 가르치면서 다시금 떠올렸었다.

그러다가 OpenCV 책을 번역하면서 발견한, union의 효과적인 사용 예를 기록해보려고 한다.

OpenCV의 행렬 구조체의 정의는 다음과 같다.

typedef struct CvMat
{
	int type;
	int step;
	int* refcount;
	int hdr_refcount;
	union {
		uchar* ptr;
		short* s;
		int* i;
		float* fl;
		double* db;
	} data;
	union {
		int rows;
		int height;
	};
	union {
		int cols;
		int width;
	};
} CvMat;


CvMat 라는 구조체 내부에 union이 두루 사용된 것을 볼 수 있다. 먼저 아래쪽 두 개의 union을 보면 rows 와 height 두 개를 union으로 감싸고 있다. 이 경우, rows 와 height 는 같은 메모리 공간을 지칭하는 변수가 된다. 즉, 행렬의 행의 크기를 나타내는 값을 rows 라는 변수로도 접근할 수 있고, height 라는 변수로도 접근할 수가 있는 것이다. 이건, 꽤 괜찮다. ^^;

두 번째, 위 구조체 정의 중간에 있는 data 라는 이름을 할당한 union은 5 가지 종류의 포인터 변수를 가지고 있는데, 이 또한 꽤 그럴싸하다. 어차피 포인터 형 변수라면 항상 4바이트(win32 환경의 경우)를 갖게 되니까 data 변수는 결과적으로 4바이트를 갖는다. 그런데 data.ptr 을 사용할 수도 있고, data.s, data.i, data.fl, data.db 를 사용할 수도 있다. 즉, CvMat 행렬이 실제 저장하고 있는 값이 무슨 타입이냐에 따라 실제 데이터가 저장된 메모리 공간을 가리키는 변수를 선택적으로 사용할 수 있는 것이다. 그러면 뭐가 좋을까??? 포인터 연산을 통해 주변 원소로 이동할 때 캐스팅을 따로 하지 않아도 되는 장점이 생긴다. (물론 주의해서 사용해야 하는 점은 존재한다.) 음... 어려울려나?? 암튼 좋은거다. ^^;

암튼, union을 사용해서 도움이 되는 예제를 처음 보다시피하여 기록해보았다. 도움이 될라나.. 흠..


Posted by kkokkal
: