C++ memcpy结构变量

C++ memcpy结构变量,c++,arrays,struct,memcpy,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

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

因为数据是数组对象,所以也可以工作吗


我们将如何复制声明为指针的结构成员data2

表达式
msg.data
的类型与表达式
&msg.data
的类型不同,但值相同。因为这是C++,所以行为在代码> > [con.PTR]/2 中非常清楚:对<代码> MeMCPY < /C>的调用导致指针参数的隐式转换为<代码> [const ] Vultu*<代码>,并且该转换的结果指向对象驻留的存储位置的开始,就好像它是一个最派生的对象一样。(不是基类子对象)”(在C中,效果是一样的,但standardese不太清楚这样说-您必须一起阅读C99第6.3.2.3节第1段和第7段,并理解
memcpy
的行为“就好像”它在内部将参数转换为指针或字符类型。)

数据
声明为

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
的表单是首选样式的原因;首先很难出错,并且在类型定义更改时不会自动出错。²

另外,就风格而言,我不喜欢在这种情况下编写
&
,因为
&[任何具有数组类型的东西]
几乎总是错误的,所以除非确实需要,否则不应该这样写

你应该知道,根据定义,
sizeof(任何种类的字符)==1
(C++[expr.sizeof]/1)。这是我个人的观点,但也是广泛认同的,这意味着
sizeof(char)
永远不应该出现在你的代码中

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


➣除了极不可能的情况,即
sizeof(unsigned char)==sizeof(unsigned int)
;这在最初的Cray上是正确的,标准仍然允许这种可能性,但恐怕很多年来没有实现者真正做到了这一点


²反驳:这是对数组类型应用
sizeof
,这是有风险的,因为数组类型“衰减”如果给指针类型一点机会,那么它同样是错误的。但是,在这种情况下-手动复制结构成员-我认为这比另一种方法危险性小。

任何一种版本都可以工作。使用符号(&)运算符显式获取数组的地址,而省略符号并使其隐式获取数组的地址。最后,结果是相同的

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

std::memcpy(msg2.data, msg1.data, sizeof(msg1.data));
这避免了输入错误,更重要的是,如果字段大小发生变化,您不必通过代码查找您使用过的位置

至于data2,zwol在下面的回答中是正确的,因为它取决于data2到底存储了什么——或者更准确地说,谁“拥有”data2以及如何释放变量。您可能需要研究“浅”复制与“深”复制。

您的最后两个
memcpy()
s应该是
sizeof(msg1.data)
不是
100*sizeof(unsigned int)
-反正它们是
unsigned char
s

但最后一点:

memcpy(msg2.data, msg2.data, 100*sizeof(unsigned int));
正确。如果要使用早期版本,请使用:

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

这两种方法都是错误的,因为如果
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

你不必强制转换指向void*;你需要强制转换来从void*@Steven我的标准内存说你错了,但我在这台计算机上没有它,所以我无法检查。它看起来像是第4.10.2节,至少是当前工作草案的:类型为“指向cv t的指针”的PR值其中T为对象类型,可转换为“指向cv void的指针”类型的prvalue@Steven在我更改答案之前,我需要确认它说了这一点或C++98中的等效项,但是谢谢。提醒:
memcpy
将复制指针
data2
,而不是
data2
指向的数据。为什么不直接使用msg2的
sizeof.data
来确定大小?也就是说,
msg2=msg1
还可以复制结构在大多数情况下,复制任何东西都是错误的,所以不要考虑使用它。例如对于固定大小的数组,你应该使用C++ <代码> STD::数组< /Cord>,这允许简单的赋值。即使没有,使用<代码> STD::复制< /代码>将更干净和更安全。我同意使用<代码> STD::复制< /代码>。它可能使用“代码> MycPy < /Cord>”。在您的实现内部,抽象将帮助您防止错误。
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