Union을 이용한 byte 단위 접근

Big-endian으로 주어진 byte들을 little-endian으로 변환해야 하는 문제가 생겼다. Byte들의 order를 거꾸로 만드는 것은 어렵지 않지만 그러기 위해서는 byte pointer가 가리키는 element들을 1 byte 단위로 접근해야 한다. 1 byte씩 뒤집은 다음에는 변환된 array를 원하는 크기의 타입으로 읽도록 type casting을 해주어야 한다.

Union을 이용하면 코드를 못생기게 만드는 pointer 직접 연산이나 type casting을 하지 않고 이를 구현할 수 있다. 즉 union은 선언된 element의 가장 큰 크기 만큼의 메모리가 할당 되므로 같은 크기의 두 element를 서로 다른 data type으로 선언하는 것이다.

union
{
  int32_t v;
  uint8_t b[4];
} value;

위와 같이 선언하면 value.v = 0xdeadbeef 같은 식으로 int32를 쓰거나 읽을 수 있고 value.b[0] 같이 각 메모리 index에 접근 할 수 있다.

Template으로 만들어서 여러 타입에 대응 할 수 있다.

    template <typename T> T readFromBigEndian(uint8_t *b)
    {
      union
      {
        T v;
        uint8_t b[sizeof(T)];
      } dest;

      union
      {
        T v;
        uint8_t *b;
      } src;

      src.b = b;
      for (int i = 0; i < sizeof(T); ++i)
      {
        dest.b[i] = src.b[sizeof(T) - i - 1];
      }
      return dest.v;
    }