memcpy结构变量

时间:2016-06-17 14:15:42

标签: c++ arrays struct memcpy

这可能听起来是一个非常基本的问题,但我在C ++中有以下结构:

struct SMessage
{
    unsigned int id; 
    unsigned int payloadSize; 
    unsigned char data[100];  
    unsigned char *data2; 
}; 

假设我有两个SMessage类型的变量(msg1,msg2),我想将msg1的个别成员memcpy到msg2(请不要问为什么!)。我知道复制id和payLoadSize是相对简单的:

memcpy(&msg2.id, &msg1.id, sizeof(unsigned int)); 
memcpy(&msg2.payLoadSize, &msg2.payLoadSize, sizeof(unsigned int));

但是为了复制数据[],我们应该这样做:

memcpy(&msg2.data, &msg1.data, 100*sizeof(unsigned char)); 

memcpy(msg2.data, msg2.data, 100*sizeof(unsigned int)) 

也可以,因为数据是一个数组对象?

我们如何复制声明为指针的struct member data2?

4 个答案:

答案 0 :(得分:2)

任何一个版本都可以使用。使用&符号(&)运算符显式获取数组的地址,而省略&符号会导致它隐式地获取数组的地址。最后,结果是一样的。

更重要的是,直接在现场使用sizeof更容易且更不容易出错:

std::memcpy(msg2.data, msg1.data, sizeof(msg1.data));

这可以避免拼写错误,更重要的是,如果字段改变了尺寸,您就不必通过代码查找已经使用过它的地方。

对于data2,zwol在他的回答中是正确的,因为它取决于data2存储的确切内容 - 或者更确切地说,取决于谁拥有" data2以及如何释放变量。你可能想看看"浅"与"深"复制。

答案 1 :(得分:0)

表达式msg.data的类型与表达式&msg.data的类型不同,但是相同的。由于这是C ++,因此在[conv.ptr]/2中非常明确地指定了行为:对memcpy的调用导致两个指针参数隐式转换为[const] void *,并且此转换的结果“指向对象所在的存储位置的开始,就好像它是一个派生程度最高的对象(不是基类子对象)“。 (在C中,效果是相同的,但是标准不太清楚 - 你必须一起阅读C99第6.3.2.3节第1和第7段并理解memcpy表现“好像”它转换了它内部指针到字符类型的参数。)

data被声明为

unsigned char data[100];  
因此,以下所有内容都是等效和正确的。其中第一个是我工作过的大多数代码库中的首选样式。

memcpy(msg2.data, msg1.data,   sizeof msg1.data);

memcpy(msg2.data, msg1.data,   100);
memcpy(msg2.data, msg1.data,   100 * sizeof(unsigned char));

memcpy(&msg2.data, &msg1.data, sizeof msg1.data);
memcpy(&msg2.data, &msg1.data, 100);
memcpy(&msg2.data, &msg1.data, 100 * sizeof(unsigned char));

然而,

memcpy(msg2.data, msg1.data, 100 * sizeof(unsigned int));

错了;它复制了太多的内存。这就是为什么带有sizeof的表单是首选的样式;首先出错是很难的,如果改变了类型定义,也不会出现错误.²

另外,作为一种风格问题,我不想在这种情况下编写&,因为&[anything with an array type]几乎总是错误的,所以不应该这样写,除非它确实是必要的。

根据定义你应该知道sizeof(any sort of char) == 1 (C ++ [expr.sizeof] / 1)。这是我个人但广泛分享的意见,这意味着sizeof(char)永远不会出现在您的代码中。

最后,我无法告诉您在没有更多信息的情况下复制data2的正确方法。我需要知道data2指向什么,如何分配,以及是否应该复制或引用它。

除了sizeof(unsigned char) == sizeof(unsigned int)的极不可能的情况外,

¹;这在原来的Cray上是正确的,标准仍然允许这种可能性,但AFAIK没有实施者在很多年里实际上已经这样做了。

²反驳:这是将sizeof应用于数组类型,这是有风险的,因为如果给出最轻微的机会,数组类型会“衰减”到指针类型,所以再次它将是默默错误的。但是,如果你在手中复制结构成员 - 我认为它比替代方案更不危险。

答案 2 :(得分:0)

你的最后两个memcpy()应该是sizeof(msg1.data)而不是100*sizeof(unsigned int) - 他们反正unsigned char了!

但是最后一个:

memcpy(msg2.data, msg2.data, 100*sizeof(unsigned int));

是对的。如果要使用前一个,请使用:

memcpy(&msg2.data[0], &msg1.data[0], 100*sizeof(unsigned int)); 

答案 3 :(得分:0)

它们都是错误的,因为如果sizeof(unsigned int)大于sizeof(char),它们会导致超出范围的访问权。

你可以做任何一个

memcpy(&msg2.data, &msg1.data, sizeof(msg1.data)); // pass pointers to arrays
memcpy(msg2.data, msg1.data, 100*sizeof(unsigned char)); // pass pointers to first elements of the arrays