首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将memcpy用于结构

将memcpy用于结构
EN

Stack Overflow用户
提问于 2013-10-09 17:55:46
回答 5查看 2.8K关注 0票数 1

在结构上使用memcpy时我遇到了一个问题。

考虑下面的结构

代码语言:javascript
运行
复制
struct HEADER
{
    unsigned int preamble;
    unsigned char length;
    unsigned char control;
    unsigned int destination;
    unsigned int source;
    unsigned int crc;
}

如果我使用memcpy将数据从接收缓冲区复制到此结构,则复制是正常的,但如果我将此结构重新声明为以下内容:

代码语言:javascript
运行
复制
struct HEADER
{
    unsigned int preamble;
    unsigned char length;
    struct CONTROL control;
    unsigned int destination;
    unsigned int source;
    unsigned int crc;
}

struct CONTROL
{
    unsigned dir : 1;
    unsigned prm : 1;
    unsigned fcb : 1;
    unsigned fcb : 1;
    unsigned function_code : 4;
}

现在,如果我使用与以前相同的memcpy代码,则前两个变量(前同步码和长度)复制正常。控制完全混乱,最后三个变量被上移一位,也就是crc = 0,source = crc,destination = source...

ANyone对我有什么好的建议吗?

EN

回答 5

Stack Overflow用户

发布于 2013-10-09 18:01:23

当您在中间添加control时,您是否知道接收缓冲区中的格式是正确的?

无论如何,您的问题是位域在这里是错误的工具:您不能依赖于内存中的布局是特定的,至少不能依赖于您为序列化表单选择的完全相同的布局。

尝试直接将结构复制到外部存储或从外部存储复制结构几乎不是一个好主意;您需要适当的序列化。编译器可以在结构的字段之间添加填充和对齐,而使用位域会使情况变得更糟。不要这样做。

实现正确的序列化/反序列化函数:

代码语言:javascript
运行
复制
unsigned char * header_serialize(unsigned char *put, const struct HEADER *h);
unsigned char * header_deserialize(unsigned char *get, struct HEADER *h);

它遍历结构并读/写所需的字节数(可能针对每个字段):

代码语言:javascript
运行
复制
static unsigned char * uint32_serialize(unsigned char *put, uint32_t x)
{
    *put++ = (x >> 24) & 255;
    *put++ = (x >> 16) & 255;
    *put++ = (x >> 8) & 255;
    *put++ = x & 255;
    return put;
}

unsigned char * header_serialize(unsigned char *put, const struct HEADER *h)
{
    const uint8_t ctrl_serialized = (h->control.dir << 7) |
                                    (h->control.prm << 6) |
                                    (h->control.fcb << 5) |
                                    (h->control.function_code);

    put = uint32_serialize(put, h->preamble);
    *put++ = h->length;
    *put++ = ctrl_serialized;
    put = uint32_serialize(put, h->destination);
    put = uint32_serialize(put, h->source);
    put = uint32_serialize(put, h->crc);

    return put;
}

请注意,这需要明确表示序列化数据的字节顺序,这是您应该始终关注的事情(我使用的是big-endian)。它还显式地构建control字段的单个结构版本,假设使用的是结构版本。

还要注意,您的CONTROL声明中有一个拼写错误;fcb出现了两次。

票数 2
EN

Stack Overflow用户

发布于 2013-10-09 18:01:29

使用struct CONTROL control;而不是unsigned char control;会导致结构内部出现不同的对齐方式,因此用memcpy()填充结构会产生不同的结果。

票数 0
EN

Stack Overflow用户

发布于 2013-10-09 18:02:11

Memcpy将字节的值从source指向的位置直接复制到destination指向的内存块。

源指针和目标指针所指向的对象的底层类型与此函数无关;结果是数据的二进制副本。因此,如果有任何结构填充,那么你就会得到混乱的结果。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19268744

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档