본문 바로가기

Coding Note

anonymus union

c의 독특한 데이터 구조인 union 이라는 아이가 있다. 먼 옛날 메모리가 귀하던 시절, 제한된 공간에서 여러 형태로 데이터를 다루기 위해서 만들어진 구조 형식인데, 메모리가 풍성해진 오늘날은 많이 사용하지 않게되었다.

 

그렇다고 union이 쓸모없어진건 절대로 아니다. 데이터의 접근을 여러 형태로 두어 c 형태의 다형성을 추구할 수단으로 사용할 수 있다.

(이게 진짜 c 형태의 다형이냐 한다면.. 할말은 없다.)

 

그래픽스 api, 특히 셰이더를 다뤄본 사람이라면 vec4의 구조에 대해서 알고있을것이다. x, y, z, w의 요소에 .x 와 같은 방식으로 접근하게 되는데, 특이하게도 .xyz와 같이 vec3의 형태를 바로 가져와 사용하기도 한다.

혹은 x, y, z, w 대신 r, g, b, a 이름으로 각 요소에 접근할 수도 있다. 물론 .rgb 이름의 vec3형태로도 접근 가능하다.

 

어떻게 이런 여러 형태의 접근을, 다시말해 하나의 변수에 여러 이름을 붙여둘 수 있을까?

union 키워드를 사용한다면 사용자 구조체(혹은 클래스) 에서도 이와같은 특징을 만들어 낼 수 있다. 다음은 c++ 클래스로 구현한 예이다.

 

class Vector4{
public:
    union{
        struct{
            Vector3 xyz;
            float w;
        };
        struct{
            float x, y, z, w;
        };
        struct{
            float r, g, b, a;
        };
    };

 

...

};

 

이름 없는 union과 그 프로퍼티로 이름 없는 struct로 메모리를 묶어주고, struct 내에서 멤버 변수를 원하는 형태로 정의하면 외부에서 접근할 때 하나의 메모리에 여러 형태로 접근할 수 있는 기능을 갖추게 된다.

 

Vector4 v;

v.xyz = Vector3(10, 20, 30);

// v.x ::= 10, v.y ::= 20, v.z ::= 30

 

이러한 형태는 유사한 클래스를 여럿 만들어야했던 시절에서 벗어나게 해준다.

 

typedef Vector4 Color;

Color color;

color.r = 1.0f; color.g = 0.8f; color.b = 0.3f; color.a = 1.0f;

 

벡터 뿐만 아니라 메트릭스도 요소의 다중배열 혹은 벡터로 표현된 행(또는 열)의 배열 형태 등 사용자가 여러 형태로 사용할 수 있도록 만들어둘 수 있다.

 

class Matrix4{
public:
    union{
        struct{
            Vector4 row[4];
        };
        struct{
            float m[4][4]; //row x col
        };
    };

};

 

Matrix4 mat;

mat.m[0][0] = 10; mat.m[0][1] = 20; mat.m[0][2] = 30; mat.m[0][3] = 40;

// mat.row[0] ::= (10,20,30,40)

 

중요한 한가지는 union으로 데이터의 형태, 혹은 이름을 결정지을 때 실제 메모리상에 어떻게 데이터가 표현되는지 확실하게 인지하고 있지 않으면 잘못된 메모리 접근이 될 수 있다는점이다. 특히 다중배열의 표현을 다양화 시킬때 메모리에 열 중심으로 표현해야하는지 행 중심으로 표현해야하는지 잘 알지 못한다면 잘못된 연산이 일어날 수도 있다. 위의 Matrix4 예에서 row[4] 대신 col[4]를 쓰면 안되는 이유를 확실히 인지하고 사용하길 바란다.

 

추가 - union struct로 기본타입이 아닌 클래스타입이 있는경우 생성자 초기화 리스트에서 멤버를 제대로 초기화 하지 못하는 문제가 발생할 수 있다. 정확한 이유는 모르겠지만, 생성자 초기화 리스트의 호출시간과 비기본타입 멤버의 메모리 초기화 시간 사이의 순서에 문제가 있을것이라 추측된다.

'Coding Note' 카테고리의 다른 글

setting polymorphic member variable.  (0) 2014.06.15
duplicated element name of different enums  (0) 2014.04.29
c++ CRTP(curiously recurring template pattern)  (0) 2014.03.02
pymongo json  (0) 2014.02.10
Flask install & test  (0) 2014.01.23