我可以为一个包含向量的C++结构写一个二进制吗

Can I make a single binary write for a C++ struct which contains a vector

本文关键字:一个 结构 C++ 二进制 包含 我可以 向量      更新时间:2023-10-16

我正在尝试构建和编写一个二进制请求,并有一个"这可能吗"类型的问题。可能对我来说很重要的一点是,请求的接受者不知道我下面包含的数据结构,它只是期望一个字节序列,但使用结构似乎是准备请求片段的一种方便方法,然后轻松地编写它们。

编写页眉和页脚是可以的,因为它们是固定大小的,但由于向量的原因,我在结构"Details"中遇到了问题。现在我正在写一个文件,这样我就可以检查请求是否符合规范,但目的是最终使用boost asio串行端口写入PLC

我可以使用这样的语法来写一个结构,但当它到达向量时,它会写指针地址而不是值

myFile.write((char*) &myDataRequest, drSize);

我可以使用这个sytax来自己编写向量,但我必须在0处包含索引器来编写值

myFile.write((char*) &myVector[0], vectorSize);

有没有一种优雅的方法可以一次完成二进制编写包含向量(或其他合适的集合)的结构?例如,如果我以不同的方式声明向量,或者我是否已经接受了对结构内内容的多次写入。如果我用数组替换向量,我可以一次性发送结构(不需要包括任何索引器),但直到运行时我才知道所需的大小,所以我认为它不合适。

我的结构

struct Header
{   ...     };
struct Details
{
std::vector<DataRequest> DRList;
};
struct DataRequest
{
short numAddresses;          // Number of operands to be read   Bytes 0-1
unsigned char operandType;   //                                  Byte 2
unsigned char Reserved1;     //Should be 0xFF                    Byte 3
std::vector<short> addressList;  // either, starting address (for sequence), or a list of addresses (for non-sequential) 
};
struct Footer
{   ...     };
这是不可能的,因为std::vector对象实际上并不包含数组,而是指向内存块的指针。然而,我很想声称,能够编写这样的原始结构是不可取的:
  1. 我认为,通过将结构视为内存块,最终可能会发送填充字节,我认为这是不可取的。

  2. 根据您写入的内容,您可能会发现写入无论如何都是缓冲的,因此多个写入调用实际上并没有降低效率。

  3. 很可能您想对发送过来的字段执行操作。特别是您发送的数值。这需要强制执行传输双方都同意的字节顺序。为了便于移植,你应该明确地转换字节顺序,以确保你的软件是可移植的(如果需要的话)。

长话短说:我怀疑逐一写出每个字段不仅效率低,而且更正确。

这不是一个很好的策略,因为即使您可以这样做,您也要将内存内容直接复制到文件中。如果您更改体系结构/处理器,您的客户端将获得不同的数据。如果您编写一个采用结构和文件名的方法,该方法单独写入结构值,并在向量上迭代,写出其内容,那么您将完全控制客户端所需的二进制格式,而不依赖于编译器的当前内存表示。

如果您想方便地进行编组/解编组,您应该查看boost::序列化库。他们确实提供了一个二进制存档(除了文本和xml),但它有自己的格式(例如,它有一个版本号,哪个序列化库用于转储数据),所以它可能不是您的客户端想要的。

另一端的格式究竟是什么?你必须写那个,周期。你不能只写任何随机的字节。概率只需像现在这样写一个std::vector就可以了尽可能接近0。但是写只有CCD_ 4的CCD_。如果其他side需要一个特定的字节序列,那么您必须编写那个序列,一个字节接一个字节。例如,要编写int,您必须仍然写四个字节(或协议要求的任何字节)类似:

byte[0] = (value >> 24) & 0xFF;
byte[1] = (value >> 16) & 0xFF;
byte[2] = (value >>  8) & 0xFF;
byte[3] = (value      ) & 0xFF;

(即使在这里,我也认为数字对应于协议的数字。通常是这样,但不是始终。)

当然,通常情况下,您在std::vector<char>中构建缓冲区,然后写入CCD_ 7。(事实上,你需要缓冲区指针的reinterpret_cast应该表示方法是错误的。)

相关文章: