这可能听起来是一个非常基本的问题,但我在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?
答案 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