目录
1.引言
在C++中有一种用户自定义数据类型叫联合体union,它允许你在相同的内存位置存储不同的数据类型。与结构体(struct
)不同,结构体中的所有成员都占用各自的内存空间,而 union
的所有成员共享同一块内存区域。因此,union
的大小等于其最大成员的大小。所以它的作用之一就是实现多种数据类型之间的转换。
示例如下:
cpp
#include <iostream>
#include <cstring> // 用于 std::memset
union MyUnion {
int intValue;
float floatValue;
char charValue;
};
int main() {
MyUnion u;
// 设置 intValue
u.intValue = 42;
std::cout << "intValue: " << u.intValue << std::endl;
// 设置 floatValue(注意:这可能会覆盖 intValue 的值)
u.floatValue = 3.14f;
std::cout << "floatValue: " << u.floatValue << std::endl;
// 设置 charValue(再次覆盖之前的值)
u.charValue = 'A';
std::cout << "charValue: " << u.charValue << std::endl;
// 清空 union(使用 memset 确保内存干净,尤其是在读取之前未设置的值时)
std::memset(&u, 0, sizeof(u));
return 0;
}
2.实际案例
在最近做的一个项目中,上位机和硬件通信,硬件会不停地把自己的一些状态参数信息上传上来,这其中包括版本号、温度、电压、解调质量等等,参数的类型大致有三种,如下图所示:
硬件为了参数上传方便,把这三种数据类型统一转换为uint64,报送给上位机,上位机根据数据类型,解析出自己的实际值,在C++语言中处理这些转换比较简单,实现如下:
uint64和char[8]转换:
定义联合体:
cpp
union stUInt64TranString
{
unsigned long long value;
char format[8];
};
比如上传的参数 "制造商" 名称为:20340163367295320
转换代码:
cpp
stUInt64TranString y;
y.value = 20340163367295320;
cout << y.format;
uint64和double转换:
定义联合体:
cpp
union stUInt64TranDouble
{
unsigned long long value;
double value1;
};
比如上传的参数 "温度" 值为:4632233691727265792
转换代码:
cpp
stUInt64TranDouble x;
x.value = 4632233691727265792;
cout << x.value1;
3.java实现
uint64转char[8]:
java
String longConvertStr(long value) {
// 使用ByteBuffer将long值转换为字节流,并设置为小端字节序
ByteBuffer byteBuffer = ByteBuffer.allocate(Long.BYTES).order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putLong(value);
// 获取字节流
byte[] bytes = byteBuffer.array();
// 去除字节流末尾的0
int length = bytes.length;
while (length > 0 && bytes[length - 1] == 0) {
length--;
}
byte[] trimmedBytes = new byte[length];
System.arraycopy(bytes, 0, trimmedBytes, 0, length);
// 尝试将去除末尾0后的字节流转换为字符串
return new String(trimmedBytes);
}
uint64转double:
java
String longConvertDouble(long value) {
ByteBuffer byteBuffer = ByteBuffer.allocate(Double.BYTES).order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putLong(value);
double recoveredValue = byteBuffer.getDouble(0);
return String.valueOf(recoveredValue);
}