使用赋值而不是memcpy()在C中复制结构

直到最近,我才看到用memcpy()复制结构字段。 在类和在线指令中,将一个结构的内容复制到另一个结构中通常看起来像

 struct block *b0 = malloc(sizeof(struct block)); struct block *b1 = malloc(sizeof(struct block)); /* populate fields in *b0 */ memcpy(b1, b0, sizeof *b1); /* copy contents of b0 into b1 */ /* free b0, b1 */ 

但是,也可以通过替换memcpy()的简单赋值来完成此任务。

 *b1 = *b0; /* dereferenced struct assignment */ 

有没有充分的理由说明为什么它没有被广泛使用(至少在我有限的经验中)? 这两个方法是赋值和memcpy()等价,还是有一些令人信服的理由一般使用memcpy()

两种方法都是等效的,并执行浅拷贝 。 这意味着复制了结构本身,但不复制结构引用的任何内容。

至于为什么memcpy更受欢迎,我不确定。 较旧版本的C不支持结构分配( 虽然它早在1978年就是常见的扩展 ),因此memcpy风格可能会成为制作更多可移植代码的一种方式? 在任何情况下,PC编译器都广泛支持结构分配,并且使用memcpy更容易出错(如果大小错误,可能会发生坏事),因此最好尽可能使用结构分配。

但是,只有memcpy有效。 例如:

  • 如果要将结构复制到未对齐的缓冲区或从未对齐的缓冲区复制 – 例如,要保存/加载到磁盘或从网络发送/接收 – 您需要使用memcpy ,因为结构分配需要源和目标正确对齐。
  • 如果要在结构之后打包附加信息(可能使用零元素数组) ,则需要使用memcpy ,并将此附加信息计入大小字段。
  • 如果要复制结构数组,那么执行单个memcpy 可能更有效,而不是单独循环和复制结构。 然后,它可能不会。 很难说, memcpy实现的性能特征不同。
  • 某些嵌入式编译器可能不支持结构分配。 当然,有问题的编译器可能还不支持其他更重要的事情。

还要注意,虽然在C memcpy和结构赋值中通常是等价的,但在C ++中memcpy和结构赋值并不等价。 在一般的C ++中,最好避免使用memcpy结构,因为结构赋值可以并且经常被重载以执行其他操作,例如深层复制或引用计数管理。

这可能不是您寻找的确切答案。

我解释了我遇到的情景。

当我们使用memcpy() ,它会逐字节地复制到目标。 所以不用担心ARM架构中的数据对齐。 如果使用=运算符,并且任何一个地址未与4字节对齐,则会出现对齐故障。

来自Arm站点:

指向目标位置的指针,该位置是写入的最后一个字节之外的一个字节。 这使得写入过程的继续with perfect alignment of bytes用于字符串串联内存块with perfect alignment of bytes

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0175k/Cihbbjge.html

我正在复活这个老问题,因为答案并没有解释为什么 memcpy实际上是首选。

memcpy是首选,因为它清楚地表明程序员想要复制内容而不是简单的指针。

在下面的示例中,两个赋值有两个非常不同的东西:

 struct Type *s1,*s2; *s1=*s2; s1=s2; 

无意中使用一个而不是另一个可能会产生灾难性的后果。 编译器不会抱怨。 除非在使用未初始化指针时程序崩溃,否则错误很长时间都会被忽视并产生奇怪的副作用。

将其写成以下之一:

 memcpy(s1,s2,sizeof(*s1)); memcpy(s1,s2,sizeof(*s2)); memcpy(s1,s2,sizeof(struct Type)); 

让读者知道目的是复制内容(以类型安全和边界检查为代价)。

有些编译器(例如gcc)甚至会在遇到类似以下内容时发出有关sizeof的警告:

 memcpy(s1,s2,sizeof(s1)); 

有些人更喜欢memcpy,因为这是他们学到的东西,他们从来没有想过他们可以做一个任务(在古代,不允许任务,但很久以前)。 没有对齐问题需要担心,因为malloc()分配的内存总是正确对齐。 而且由于编译器可以将这个赋值简单地转换为memcpy调用,因此它永远不会比memcpy更慢或更多代码。 当然,嵌入式系统中存在严重过时的编译器。

在嵌入式平台上工作的人更愿意使用memcopy而不是直接分配结构。 主要是当您处理嵌入式平台时,某些编译器不支持直接结构分配,因为您需要使用memcopy。 如果您正在使用PC,那么在任何一种情况下都没有问题,两者都是有效的。