神奇的union

  共用体union作为一种复合结构,当某个数据有多种表示类型的时候使用union可以很好的节省内存。比如,如果一个商品的id可以用int、double、long long来存储,那么就可以使用union来存储。union和结构体不同,结构体可以同时存储多个不同的数据类型,union只能存储多个类型中的一个。
  目前我在开发项目的过程中基本遇不到内存有较强限制的场合,很少用到union这种复合结构。但是,最近在解析velodyne-16雷达数据的时候,发现了union很巧妙的用法。

velodyne-16数据格式

  velodyne-16线雷达在Single Return模式下的每个udp包中包含了12个数据块,每个数据块的结构为开始标记、方位角、两组16个通道的点云数据。如下图所示:

方位角的计算

  其中解析方位角度的时候,计算规则如下:
  假设方位角的两个byte分别为0x33和0x77,我们需要将其字节序交换并拼接为0x7133,然后转换为十进制,计算结果为28979。将转换后的值除以100得到的289.79便是该数据块的方位角。点云的距离值占两个字节,计算方式和方位角也一样。
  对于这种解析规则,我们可以先转换成string,再转换为int的方式完成,但是相对来说比较麻烦。

union的使用

  在编写解析代码的时候,发现有人使用union来理这种解析规则,具体操作为:
  1.定义一个union结构体,其中有两种类型,第一种类型为unsigned char bytes[2],第二种类型为unsighed short values,这样两种类型的值在字节数上刚好一致。
  2.按照顺序填充bytes的两个字节,然后直接读取value的值便是最终的转换结果。
  定义如下:

union two_bytes {
    unsigned char bytes[2];
    unsigned short value;
};

  对以上方法进行测试:

#include <bits/stdc++.h>
using namespace std;
union two_bytes {
    unsigned char bytes[2];
    unsigned short value;
};
int main() {
    two_bytes tb = {0x33, 0x71};
    cout << "tb.value = " << tb.value << endl;
    return 0;
}

  代码输出的结果如下:

tb.value = 28979

分析

  使用union极大地简化了这一解析步骤,其原理应该和存储的字节序有关系。目前来说,在windows上的效果如此,暂时还没有探究大端和小端模式是否会真的影响这一过程。当下,先做一记录,等到空闲的时候再一探究竟。


当珍惜每一片时光~