【问题标题】:Difference between memcpy and copy by assignmentmemcpy 和按赋值复制的区别
【发布时间】:2018-07-12 06:46:52
【问题描述】:
Struct A
{
   uint16_t len;
   uint8_t  cnt;
   uint8_t  unit;
   uint32_t seq; 
};

这个结构体A被序列化成一个char * buf。如果我想反序列化单个值,例如:

uint16_t len = 0;
memcpy(&len, buf, sizeof(len));

或者我可以这样做

uint16_t len = (uint16_t) buf;

哪个更好,或者两者都一样?

如果我只是这样做的话,也可以反序列化整个结构

A tmp;

memcpy(&tmp, buf, sizeof(A));

这样可以正常工作还是我应该担心编译器的填充等?

【问题讨论】:

  • 您的意思可能是len = *(uint16_t*)buf。嗯,这是一个严格的别名规则违规。
  • 什么是严格的别名规则违规?
  • 这是另一个问题,其实已经回答过很多次了。 stackoverflow.com/questions/98650/…
  • C++ 标签是否相关?

标签: c++ c memcpy


【解决方案1】:

当数据被复制到char[] 缓冲区时,它可能无法在内存中正确对齐以作为多字节类型访问。将数据复制回struct 可恢复正确对齐。

如果我想反序列化单个值,例如:

uint16_t len = 0;
memcpy(&len, buf, sizeof(len));

假设您已将struct 复制到buf,这是完全有效的,因为该语言保证初始成员将与结构的开头对齐。但是,将buf 转换为uint16_t* 是无效的,因为许多缓冲区在内存中没有正确对齐以被寻址为uint16_t

请注意,获取除初始元素之外的结构元素需要计算适当的偏移量:

uint32_t seq;
memcpy(&seq, buf+offsetof(struct A, seq), sizeof(seq));

如果我这样做的话,也可以反序列化整个结构

A tmp;
memcpy(&tmp, buf, sizeof(A));

这样可以正常工作还是我应该担心编译器的填充等?

这会很好。当您将 struct 复制到 buf 中时,嵌入在 struct 中的任何填充将连同实际数据一起返回到 tmp

【讨论】:

  • 对不起,我的意思是len = *(uint16_t*)buf
  • @EternalLearner 是的,我认为您的意思是转换为指针和取消引用,这就是为什么我写了关于将 buf 转换为 uint16_t* 指针的原因。
  • 那么 memcopy 和做这个作业拷贝会有区别吗?如果是,那会是什么?首选哪种方法?
  • @EternalLearner 如果您通过网络获得struct,则该方法将是不安全的,除非发件人使用兼容的硬件。如果没有,您需要使用ntoh/hton 制定一些协议。
  • @EternalLearner 理想情况下,您开发一个正式的协议 用于串行传输数据(通过网络或其他方式),然后在发送方和接收方都遵守该协议。如果您明智地设置协议,那么这样做还有一个额外的优势,那就是独立于平台;将结构转储到缓冲区,发送,然后将缓冲区转储到结构中的东西非常缺乏。
猜你喜欢
  • 2015-01-19
  • 2011-07-19
  • 1970-01-01
  • 2014-05-18
  • 2011-06-03
  • 2015-03-03
  • 2014-04-26
  • 2014-05-02
  • 1970-01-01
相关资源
最近更新 更多