我需要将我的结构序列化为二进制流。这是这个结构的样子,以及我如何尝试序列化它。我想我的序列化分数得到了错误的值。有人可以看一下并确认我的方式应该有效吗?
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();
}
};
答案 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_t
和float
的默认打印表示不使用相应的ASCII字符。相反,您应该看到value == 65.0
和date == 66
。
答案 1 :(得分:0)
float
的二进制布局与整数类型不同。
包含整数值float
的{{1}}不包含包含'A'
的字节,这并不足为奇。