繁体   English   中英

序列化/反序列化 c++ 中的位域结构

[英]Serializing/deserializing a bitfield structure in c++

我有一个

typedef struct {
    uint32_t  Thread: HTHREAD_BUS_WIDTH; 
    uint32_t Member: 3;                  
    uint32_t Proxy:3;  
// Other members, fill out 32 bits                 
} MyStruct;

我必须从一个系统传输到另一个系统作为包含 32 位字的缓冲区的一项。

序列化结构以及反序列化它的最佳方法是什么? “最佳”在这里意味着安全铸造,没有不必要的复制。 对于一个铸造方向,我发现(作为成员函数)

int &ToInt() {
    return *reinterpret_cast<int *>(this);}

是否有类似的有效转换,即从 integer 到 MyStruct; 最好的成员是 function?

如何定义哪个位表示哪个字段? (甚至可能是反序列化发生在另一个程序、另一种语言、小/大端系统中?

如何定义哪个位表示哪个字段?

你不能。 您无法控制位域的布局。

“最佳”在这里意味着安全铸造,没有不必要的复制。

没有可以避免复制的便携式安全演员。


序列化位域的一种可移植方法是按所需顺序手动转换为 integer。 例如:

MyStruct value = something;
uint32_t out = 0;
out |= value.Thread;
out << HTHREAD_BUS_WIDTH;
out |= value.Member;
out << 3;
out |= value.Proxy;

在所示示例中,最低有效位包含字段Proxy ,而其他字段在更高有效位中相邻。

当然,为了正确序列化这个生成的 integer,就像序列化任何 integer 一样,您必须考虑字节顺序。 integer 的序列化可以通过重复移动 integer 并将字节按重要性顺序复制到数组中来实现。

如果您需要从可能具有不同字节顺序的其他系统读取,则不能依赖可移植位域。 一种解决方案是“扩展”您的结构,以便每个字段在“传输”缓冲区中序列化为 32 位值。 一个安全的实现可能是这样的:

typedef struct {
    uint32_t  Thread: HTHREAD_BUS_WIDTH; 
    uint32_t Member: 3;                  
    uint32_t Proxy:3;  
// Other members, fill out 32 bits                 
   std::vector<uint32_t > to_buffer() const;
} MyStruct;

to_buffer()的实现:

std::vector<uint32_t > MyStruct::to_buffer() const
{
   std::vector<uint32_t> buffer;
   buffer.push_back((uint32_t )(Thread);
   buffer.push_back((uint32_t )(Member);
   buffer.push_back((uint32_t )(Proxy);
   // push other members

  return buffer;
}

然后在接收端你可以做“缓冲区”来构建。

如果您不想扩展不使用 32 位的字段,您始终可以通过移位和屏蔽位来实现自己的打包 function,例如:

uint32_t menber_and_procy = (Member << 3) | proxy; // and so one for other members.

它更容易出错。

根据我自己的经验,如果通信带宽不是问题,那么依靠“类似文本”的内容是更好的选择(没有字节序问题并且非常容易调试)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM