C++ “二进制”;散装;位字段的序列化

C++ “二进制”;散装;位字段的序列化,c++,serialization,binary,deserialization,bit-fields,C++,Serialization,Binary,Deserialization,Bit Fields,我有很多布尔属性的对象,所以我使用位域来压缩属性。我还希望能够以紧凑的方式序列化和反序列化这些属性,例如,不是逐个字段,而是通过序列化和反序列化包含字段的64位uint。这种方法不仅速度快得多(例如,避免所有的移位和填充),而且内存效率提高了8倍 然而,我读到该标准并不能保证不同平台上的位域实现是统一的。我能期望比特域容器的“大容量”二进制序列化在不同平台上产生统一的结果吗?或者,在处理属性时,使用手动移位和掩蔽可能会更安全,以便可以进行批量序列化和反序列化?平台端点的变化表明,任何此类序列化都

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


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

平台端点的变化表明,任何此类序列化都是不可移植的。基于此,我想说,您不能期望比特域容器的大容量二进制序列化在不同平台上是统一的

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

您可以查看:

它为和提供定义良好的函数。定义位集中的第一位是
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);
std::位集位;
无符号long-long val=位到_ullong();
//序列化您的ullong值
//从序列化数据加载ullong
无符号长值2=。。。;
std::位集新比特(val2);
因此,只要序列化能够正确地加载/存储
无符号long
,就可以了


唯一的问题是当您的位字段对于
无符号long
来说太大时。在这种情况下,标准没有提供提取位字段的简单方法。

一种可能是使用ASN.1通过位字符串处理此问题。它以独立于本地表示的方式精确定义序列化。这使得它在不同平台之间保持一致,而不管本地平台是big-endian还是little-endian。您可以在上玩免费的在线ASN.1编译器和编码器/解码器,以查看结果序列化


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

这可能会对您有所帮助,这是各种序列化类型的一个小示例。 我添加了位集和原始位值,可以像下面那样使用

(所有示例均位于)

class位集类{
公众:
std::位集a;
std::位集b;
std::位集c;
unsigned int d:1;//需要c++20作为位字段的默认初始值设定项
无符号整数e:2;
无符号整数f:3;
BitsetClass(void){d=0;e=0;f=0;}
friend std::ostream和运算符位(my.t.c);
std::位集s;
在>>位中;
无符号长原始位=静态转换(s.到uulong());
my.t.d=原始位&0b00001;
my.t.e=(原始位&0b000110)>>1;
my.t.f=(原始位&0b111000)>>3;
返回(in);
}
};

您使用的是哪种位字段<代码>标准::位集?@MatthiasB-没有普通的旧C位字段。
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);
    }
};