首页 > 解决方案 > (反)在c ++中序列化包含__uint128_t的结构

问题描述

我正在尝试序列化和反序列化包含 __uint128_t 数据类型的结构向量。以下是尝试编写一个简化版本,而不使用 sizeof(Test) 进行序列化:

typedef __uint128_t data_t;
//typedef uint64_t data_t;

struct Test {
data_t element;
int count;

Test()=default;

};

template<typename POD>
std::ostream& serialize(std::ostream& os, const POD& v)
{
  static_assert(std::is_trivial<POD>::value && std::is_standard_layout<POD>::value,
    "Can only serialize POD types with this function");

  printf("in POD, sizeof(POD): %lu\n", sizeof(v));
  os.write(reinterpret_cast<const char*>(&v), sizeof(POD));
  return os;
}

template<typename POD>
std::istream& deserialize(std::istream& is, POD& v)
{
  static_assert(std::is_trivial<POD>::value && std::is_standard_layout<POD>::value,
    "Can only deserialize POD types with this function");

  is.read(reinterpret_cast<char*>(&v), sizeof(POD));
  return is;
}

int main()
{

 std::string tmp_buffer;
 std::stringstream oss;
 
 std::vector<Test>data_in(2);

 data_in[0].element=2345;
 data_in[0].count=4;

 data_in[1].element=5431;
 data_in[1].count=10;

 serialize(oss, data_in[0].element);
 serialize(oss, data_in[0].count);
 serialize(oss, data_in[1].element);
 serialize(oss, data_in[1].count);

 tmp_buffer = oss.str();
 printf("buffer len: %lu\n", tmp_buffer.size());

 Test k1;
 deserialize(oss, k1.element);
 deserialize(oss, k1.count);
 printf("data_out0: element: %llu, count: %d\n", k1.element, k1.count);

 Test k2;
 deserialize<data_t>(oss, k2.element);
 deserialize<int>(oss, k2.count);
 printf("data_out1: element: %llu, count: %d\n", k2.element, k2.count);

 assert(data_in[0].element == k1.element);
 assert(data_in[0].count == k1.count); /* passes ? */

 int c=k1.count;
 Test x = Test{k1.element, c};
 printf("c: %d, element: %llu, count: %d\n", c, x.element, x.count);

 return 0;

}

输出如下:

in POD, sizeof(POD): 16
in POD, sizeof(POD): 4
in POD, sizeof(POD): 16
in POD, sizeof(POD): 4
buffer len: 64
data_out0: element: 2345, count: 0
data_out1: element: 5431, count: 0
c: 4, element: 2345, count: 0

count 的值打印为0,即使它通过了 assert 语句。为什么我看到正确的值 forelement而不是 for count

如果data_t设置为,则输出对于和uint64_t的值都是正确的。为什么我看到此案的差异?elementcount__uint128_t

标签: c++serializationdeserialization

解决方案


断言通过是因为它的条件为真。问题实际上是您尝试x.elementx.count. x.element是扩展整数类型,C标准库中不支持打印扩展整数(C标准中不存在扩展整数),所以printf不知道如何处理你给它的数据。无法保证printf在这种情况下会做什么;它依赖于实现。更不用说,你试图用 打印它%llu,暗示它是一个unsigned long long,但它不是。Anunsigned long long保证至少有 64 字节的空间;您的扩展整数类型需要 128 个字节的空间。

如果你不打印x.element,那么x.count打印就好了。


推荐阅读