实际工作中碰到一个需求,将一个double类型的变量,存储成两个float类型。最后再根据两个float类型转回double类型。因为实际的信号列表已经定义了好了两个float类型,所以只能以这种折中的方法将double类型存储下来。
目录
1、按字节存储的方法
首先想到的是一个double类型和两个float类型都占据8字节,所以把一个double拆成两个4字节分别存储是可行的。代码如下:
void splitDoubleIntoTwoFloats(double value, float &part1, float &part2) {
unsigned char bytes[8];
// 利用memcpy函数,将value地址里的存储内容8字节,存储到字节的数组里,
memcpy(bytes, &value, 8);
unsigned char floatBytes1[4];
unsigned char floatBytes2[4];
// 将double的4字节复制到第一个float
std::copy(bytes, bytes + 4, floatBytes1);
// 将double的后4字节复制到第二个float
std::copy(bytes + 4, bytes + 8, floatBytes2);
// 将字节转换回float
memcpy(&part1, floatBytes1, 4);
memcpy(&part2, floatBytes2, 4);
}
2、不借助中间的字节数组
完成上述功能之后发现,代码写的有点繁琐,其实就是将double的高低四字节分别存储进float,因为float的实际数值直观上没有具体含义,最后还是要取float里的字节拼回double,所以可以直接存进float里。代码如下:
void splitDoubleIntoTwoFloats(double value, float& part1, float& part2) {
float result[2];
memcpy(&result, &value, sizeof(value));
part1 = result[0];
part2 = result[1];
}
3、继续优化中间变量
其实并不需要把每个float列出来,既然float都是中间变量,就用一个float数组存储起来就好。实际上述代码中以及使用了,但为了分别输出两个float(实际没有必要),还是显得有些冗余,可以直接用一个float数组代替。代码如下:
void splitDoubleIntoTwoFloats(double value, float* arr) {
memcpy(arr, &value, sizeof(value));
}
这样就显得简洁很多。这里要注意传入数组作为形参,需要用指针的形式,表示传入的是数组。而在函数体内部,arr足以表示数组的首地址,所以memcpy的第一个参数写成arr即可。
4. 功能验证
#include <iostream>
#include <cstring>
using namespace std;
void splitDoubleIntoTwoFloats(double value, float* arr) {
memcpy(arr, &value, sizeof(value));
}
void TwoFloatsToDouble(float* arr, double& result){
memcpy(&result, arr, sizeof(result));
}
int main(){
double a = 1.3445656;
double b;
float arr[2];
splitDoubleIntoTwoFloats(a, arr);
cout << arr[0] << " " << arr[1] << endl;
TwoFloatsToDouble(arr, b);
cout << "a: " << a << " b: " << b << endl;
return 0;
}
输出结果:
2.92332e-05 1.91807
a: 1.34457 b: 1.34457