我正在为avr芯片编写一个函数,将字节流反序列化为基本类型.我想以尽可能通用的方式进行,并且想知道确定反序列化类型的最佳实践是什么.我到目前为止的想法包括:
选择A:
// Just write a function for each type
double deserialize_double(uint8_t *in) { }
选择B:
// Use a template, and pass the type in when calling
// Function:
template <typename TYPE>
TYPE deserialize(uint8_t *in) {
union {
TYPE real;
uint8_t base[sizeof(TYPE)];
} u;
for (unsigned int i = 0; i < sizeof(TYPE); i++) {
u.base[i] = in[i];
}
return u.real;
}
// Call:
double value = deserialize<double>(in);
选择C:
// Similar to B, but you pass in the type as a parameter
// Function:
TYPE deserialize(uint8_t *in, TYPE);
// Call:
double value = deserialize(in, double);
选择D:
// Use a templated class. My main issue with this is I was hoping
// to re-use the same object for deserializing multiple types.
template <typename TYPE>
class Serializer {
public void serialize(uint8_t *out, TYPE value) { /* code */ }
public TYPE deserialize(uint8_t *int) { /* code */ }
};
有关最佳方法的任何想法吗?也许我忽略了一种更简单的方法.
解决方法:
对于初学者,C和D是无效选项,因为类型不是有效的函数参数;不妨现在就把它们排除在外.
选择B在这里似乎是明显的赢家,假设您不关心字节排序或其他使用联合的潜在警告(看起来您不会得到这项工作的背景).
另外需要考虑的是在反序列化时使用一些反馈机制来推进字节流指针/索引.也许你可以试试像
template <typename TYPE>
int deserialize(uint8_t *in, TYPE& value) {
union {
TYPE real;
uint8_t base[sizeof(TYPE)];
} u;
for (unsigned int i = 0; i < sizeof(TYPE); i++) {
u.base[i] = in[i];
}
value = u.real;
return sizeof(TYPE);
}
// Call:
double foo, bar;
int baz;
in += deserialize(in, foo); // Implicit double deserialize
in += deserialize(in, bar); // Implicit double deserialize
in += deserialize(in, baz); // Implicit int deserialize
这有额外的优势(正如我看到@Asha已经打败了我!)允许你利用C模板的类型推理系统;由于第二个参数在调用位置具有已知类型,因此无需为TYPE显式指定模板参数.