[英]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.