【发布时间】:2015-09-30 02:52:28
【问题描述】:
我已将嵌入式设备连接到 PC
以及一些具有许多自定义类型 FixedPoint_t 的字段和数组的大型结构 S。
FixedPoint_t 是一个模板化的 POD 类,它只有一个数据成员,其大小根据模板参数从 char 到 long 不等。无论如何它通过了static_assert((std::is_pod<FixedPoint_t<0,8,8> >::value == true),"");
如果这个大结构在嵌入式系统和控制 PC 上都具有兼容的底层内存表示,那就太好了。这允许将通信协议显着简化为诸如“将具有偏移 N 的字/字节设置为值 V”之类的命令。假设两个平台上的字节顺序相同。
我在这里看到了 3 个解决方案:
使用像 #pragma 这样的东西在两边都打包。 但是当我将 attribute((packed)) 放入 struct S 声明时收到警告 警告:由于未打包的非 POD 字段而忽略打包属性。 这是因为 FixedPoint_t 未声明为 packed。 我不想将它声明为打包,因为这种类型在整个程序中被广泛使用,打包会导致性能下降。
进行正确的结构序列化。这是不可接受的,因为代码膨胀,额外的 RAM 使用...协议会更复杂,因为我需要随机访问结构。现在我认为这不是一个选择。
手动控制填充。我可以添加一些字段,重新排序其他字段......只是为了在两个平台上都没有填充。这会让我暂时满意。但是我需要一个好的方法来编写一个测试来显示我是否存在填充。 我可以将 sizeof() 每个字段的总和与 sizeof(struct) 进行比较。 我可以比较两个平台上的每个结构字段的 offsetof()。 两种变体都够丑的……
你有什么推荐的?特别是我对测试中的手动填充控制和自动填充检测感兴趣。
编辑: 在两个平台上比较 sizeof(big struct) 是否足以检测布局兼容性(假设字节序相等)?如果填充不同,我认为大小不应该匹配。
EDIT2:
//this struct should have padding on 32bit machine
//and has no padding on 8bit
typedef struct
{
uint8_t f8;
uint32_t f32;
uint8_t arr[5];
} serialize_me_t;
//count of members in struct
#define SERTABLE_LEN 3
//one table entry for each serialize_me_t data member
static const struct {
size_t width;
size_t offset;
// size_t cnt; //why we need cnt?
} ser_des_table[SERTABLE_LEN] =
{
{ sizeof(serialize_me_t::f8), offsetof(serialize_me_t, f8)},
{ sizeof(serialize_me_t::f32), offsetof(serialize_me_t, f32)},
{ sizeof(serialize_me_t::arr), offsetof(serialize_me_t, arr)},
};
void serialize(void* serialize_me_ptr, char* buf)
{
const char* struct_ptr = (const char*)serialize_me_ptr;
for(int i=0; i<SERTABLE_LEN; I++)
{
struct_ptr += ser_des_table[i].offset;
memcpy(buf, struct_ptr, ser_des_table[i].width );
buf += ser_des_table[i].width;
}
}
【问题讨论】:
-
请不要编辑/扩展您的问题。这不是讨论论坛。如果还有其他问题,请提出新问题。但首先,尝试自己,对你得到的答案的各个方面进行一些研究。 (memcpy 不是序列化的正确方法。有关我在另一个答案中提供的示例,请参阅here,以了解正确序列化的想法。我的方法不关心填充。还要注意@ 987654325@ 及其设置实际上可能需要比移位更长的时间(这是高度可优化的)。
-
似乎这是序列化和协议 C++ 实现的一个很好的例子。 youtu.be/wbZdZKpUVeg
标签: c++ c++11 struct embedded padding