【问题标题】:How to convert any value to byte array and append it to a byte list?如何将任何值转换为字节数组并将其附加到字节列表?
【发布时间】:2019-11-11 10:18:11
【问题描述】:

我想为我的小游戏引擎编写一个自定义二进制文件。 我使用过 C#,并且知道如何在 C# 中使用 BitConvert 或 Convert 进行操作。

但由于某些原因,我需要在 C++ 中做同样的事情。

这是我的数据结构:

Mesh Position    point3(x,y,z)       type: float   size: 4bytes *3 = 12bytes
Mesh Options     point3(b1,b2,b3)    type: bool    size: 1byte  *3 = 3bytes
Mesh Scale       point3(x,y,z)       type: int     size: 4bytes *3 = 12bytes
Mesh Tag         single              type: string  size: 8bytes *1 = 8bytes

现在我有一个无符号字符列表:

vector<unsigned char> binary_data;

我可以使用 push 向其中添加单个字节,最后用 ofstream 写入:

ofstream fout;
fout.open("file.bin", ios::binary | ios::out);

vector<unsigned char> binary_data;

binary_data.push_back(0x66);
binary_data.push_back(0xFF); // bool : true
binary_data.push_back(0x00); // bool : false

fout.write((char*)binary_data.data(),binary_data.size());

fout.close();

我的问题

我需要将任何类型的 float、int、bool、uint、double 值转换为字节数组并将其附加到我的向量列表中。

再次获取它们并将它们转换回原始值。

偏移量和字节大小都是已知的。

这是一个例子:场景中有两个网格..

  • 第一个比例:point3(10,5,15)
  • 秒刻度:point3(25,0,5)

现在我得到 x y z 并将它们转换为 4 个字节:

10 = > 00 00 00 0A
5 = > 00 00 00 05
15 = > 00 00 00 0F
25 = > 00 00 00 19
0 = > 00 00 00 00
5 = > 00 00 00 05

我将它们附加到binary_data 列表中。

如何将它们转换为字节数组并返回?

【问题讨论】:

  • 您可以对地址使用(char*) 强制转换。虽然我相信你更应该查找序列化技术。
  • @πάνταῥεῖ 我需要学习它来制作我自己的序列化系统。
  • 您的代码将依赖于平台(准确地说是依赖于字节序)。您需要在代表变量的每个字节序列的开头添加另一个字节来说明类型(例如,0 表示int,1 表示float,等等)。
  • @goodvibration 我没关系,它只适用于 pc 和 windows

标签: c++ arrays binary


【解决方案1】:

你可以像这样使用std::memcpy

#include <cstring>
#include <vector>
#include <type_traits>

template <typename T> void serialize(std::vector<char> &v, const T &obj) {
  static_assert(std::is_trivially_copyable<T>::value,"Can only serialize trivially copyable objects.");
  
  auto size = v.size();
  v.resize(size + sizeof(T));

  std::memcpy(&v[size], &obj, sizeof(T));
}

可以类似地进行反序列化,也可以在复制到现有对象和创建新对象之间进行选择。

template <typename T>
void deserialize(const std::vector<char> &v, std::size_t offset, T &obj) {
  static_assert(std::is_trivially_copyable<T>::value,"Can only deserialize trivially copyable objects.");
  
  std::memcpy(&obj, &v[offset], sizeof(T));
}
template <typename T>
T deserialize(const std::vector<char> &v, std::size_t offset) {
  static_assert(std::is_trivially_copyable<T>::value,"Can only deserialize trivially copyable objects.");

  T obj;  
  deserialize(v,offset,obj);
  return obj;
}

在进行任何类型转换之前,您应该熟悉 strict aliasing rule

请注意,只有trivially_copyable 类型可以用memcpy 序列化,并且不要用指针序列化任何类。当然,除非强制执行 T 中的特定布局,否则这些都不兼容机器、架构或编译器。

【讨论】:

  • 这意味着所有的值都是相同的类型。
  • 不,不是吗? OP 表示他们可以访问所有尺寸和偏移量。
  • 如何循环调用这个函数?
  • @Quimby 谢谢你,是的,所有数据都是固定的,并且是已知大小的偏移量。
  • @LinkinGarden 我很高兴听到这个消息 :)
猜你喜欢
  • 2010-11-04
  • 2011-03-11
  • 2014-08-08
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多