【问题标题】:Binary "bulk" serialization of bitfields位域的二进制“批量”序列化
【发布时间】:2014-09-20 23:28:28
【问题描述】:

我有很多布尔属性的对象,所以我使用位域来更紧凑地打包属性。我还希望能够以紧凑的方式序列化和反序列化这些属性,例如不是逐个字段,而是通过序列化和反序列化保存字段的 64 位 uint。这种方式不仅速度更快(例如,避免所有的移位和其他东西),而且内存效率提高了 8 倍。

但是,我读到该标准不保证位域实现在不同平台上是统一的。我可以期望位域容器的“批量”二进制序列化会在平台之间产生统一的结果吗?或者在使用属性时进行手动移位和屏蔽可能更安全,以便批量序列化和反序列化成为可能?

【问题讨论】:

  • 您使用的是哪种位域? std::bitset?
  • @MatthiasB - 没有普通的旧 C 位字段。

标签: c++ serialization binary deserialization bit-fields


【解决方案1】:

你可以看看std::bitset

它为cast your bits into an unsigned long longcreate a bitset from a stored unsigned long long 提供了定义明确的函数。定义bitset中的第一位是ullong表示的最低有效位。

所以你可以有类似的东西:

 std::bitset<N> bits;
 unsigned long long val = bits.to_ullong();
 // serialize your ullong value
 // load ullong from serialized data
 unsigned long long val2 = ...;
 std::bitset<N> newBits(val2);

所以,只要您的序列化可以正确加载/存储unsigned long long,您就可以开始了。

唯一的问题是当你有一个对于unsigned long long 来说太大的位域。在这种情况下,标准没有提供提取位域的简单方法。

【讨论】:

    【解决方案2】:

    一种可能性是使用 ASN.1 通过 BIT STRING 来处理这个问题。它以一种独立于本地表示的方式精确地定义了序列化。这允许它跨平台保持一致,无论本地平台是大端还是小端。您可以在http://asn1-playground.oss.com 使用免费的在线 ASN.1 编译器和编码器/解码器来查看生成的序列化。

    ASN.1 还允许您为每个位指定一个“名称”,以便您可以轻松设置或检查位字符串中的每个命名位。

    【讨论】:

      【解决方案3】:

      平台字节序的变化表明任何此类序列化都是不可移植的。基于此,我会说你不能期望位域容器的批量二进制序列化跨平台是统一的。

      解决方案必须考虑位顺序并根据平台进行更正。

      【讨论】:

        【解决方案4】:

        这可能会对您有所帮助,它是各种序列化类型的一个小例子。 我添加了 bitset 和 raw bit 值,可以像下面这样使用。

        https://github.com/goblinhack/simple-c-plus-plus-serializer 的所有示例)

        class BitsetClass {
        public:
            std::bitset<1> a;
            std::bitset<2> b;
            std::bitset<3> c;
        
            unsigned int d:1; // need c++20 for default initializers for bitfields
            unsigned int e:2;
            unsigned int f:3;
            BitsetClass(void) { d = 0; e = 0; f = 0; }
        
            friend std::ostream& operator<<(std::ostream &out,
                                            Bits<const class BitsetClass & > const m
            {
                out << bits(my.t.a);
                out << bits(my.t.b);
                out << bits(my.t.c);
        
                std::bitset<6> s(my.t.d | my.t.e << 1 | my.t.f << 3);
                out << bits(s);
        
                return (out);
            }
        
            friend std::istream& operator>>(std::istream &in,
                                            Bits<class BitsetClass &> my)
            {
                std::bitset<1> a;
                in >> bits(a);
                my.t.a = a;
        
                in >> bits(my.t.b);
                in >> bits(my.t.c);
                std::bitset<6> s;
                in >> bits(s);
        
                unsigned long raw_bits = static_cast<unsigned long>(s.to_ulong());
                my.t.d = raw_bits & 0b000001;
                my.t.e = (raw_bits & 0b000110) >> 1;
                my.t.f = (raw_bits & 0b111000) >> 3;
        
                return (in);
            }
        };
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-01-04
          • 2018-06-29
          • 2016-07-27
          • 1970-01-01
          • 2011-07-12
          • 1970-01-01
          • 2012-09-12
          相关资源
          最近更新 更多