序列化结构

时间:2015-02-24 21:49:37

标签: c++

我需要将我的结构序列化为二进制流。这是这个结构的样子,以及我如何尝试序列化它。我想我的序列化分数得到了错误的值。有人可以看一下并确认我的方式应该有效吗?

struct Termometer {
public:
  byte* address;
  uint32_t name;
  float valueC;
  uint64_t time;

  ContentPair ToFlat() {
    uint32_t objSize = sizeof(name) + sizeof(valueC) + sizeof(time);
    byte* bytes = new byte[objSize];

    uint32_t* namePtr = (uint32_t*) &bytes[0];
    namePtr[0] = name;

    float* valuePtr = (float*)&bytes[4];
    valuePtr[0] = valueC;

    uint64_t* timePtr = (uint64_t*)&bytes[8];
    timePtr[0] = time;

    ContentPair pair;
    pair.rawBytes = (void*) bytes;
    pair.size = objSize;
    return pair;
  }
};

使用此值:

Termometer t;
t.valueC = 'A';
t.time = 'B';
t.name = 'C';
ContentPair content = t.ToFlat();
content.Print(); 
它给了我:

C000000BB0000000

这是struct ContentPair:

struct ContentPair
{
  void* rawBytes;
  uint32_t size;

  void Print() {
    char* bytes = (char*)rawBytes;
    Serial.print("Size is: ");
    Serial.println(size);
    for(int i = 0; i < size; ++i)
    {
      if(bytes[i] == 'A' || bytes[i] == 'B' || bytes[i] == 'C')
        Serial.print(bytes[i]);
      else
        Serial.print('0');
    }
    Serial.println();
  }
};

2 个答案:

答案 0 :(得分:2)

您误解了测试代码的作用。分配float值时,例如:

t.valueC = 'A';

你应该对为什么甚至编译感到怀疑。毕竟,字母 A 不是数字!但是,char文字'A' 具有数值,因此编译器很乐意将其静默转换为赋值给float类型的变量。它的值是(在大多数实现中)65。因此,您已将值65.0分配给结构的float字段。

IEEE float值65.0的二进制表示为01000010100000100000000000000000.(我使用了IEEE 754 converter from Harald Schmidt。)在十六进制中,即0x42820000。然后将字节与字母进行比较。字节是数字,因此再次发生相同的字母到数字转换。数据中没有值为65的字节,因此您的输出中没有任何 A 。但是,你有两个 B 。第一个来自date字段的最低有效字节(因为这是您指定的字段),而下一个字节来自value字段的最高有效字节。如上所示,第一个字节的值为0x42,十进制为66.如果'A'为65,则'B'为66是很自然的。

到目前为止,您的代码中的主要错误是测试 - 您没有看到您期望看到的内容,但您的期望是错误的。您已经编写了序列化代码。如果您编写用于反序列化的类似代码并将其应用于序列化数据,则应该获得与您输入的值相同的值。(但是,如果您打印这些值,则仍然< / em>不会看到 A B ,因为uint64_tfloat的默认打印表示不使用相应的ASCII字符。相反,您应该看到value == 65.0date == 66

答案 1 :(得分:0)

float的二进制布局与整数类型不同。

包含整数值float的{​​{1}}不包含包含'A'的字节,这并不足为奇。