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

时间:2012-11-08 06:57:44

标签: c pointers struct memcpy

直到最近,我才看到用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()

5 个答案:

答案 0 :(得分:29)

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

至于为什么memcpy更受欢迎,我不确定。较旧版本的C不支持结构赋值(although it was a common extension as early as 1978),所以memcpy样式可能会成为制作更多可移植代码的方式吗?在任何情况下,PC编译器都广泛支持结构分配,并且使用memcpy更容易出错(如果你的大小错误,可能会发生坏事),所以最好使用结构赋值可能的。

但是,只有memcpy有效的情况。例如:

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

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

答案 1 :(得分:6)

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

我解释了我遇到的情景。

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

来自Arm网站:

指向目标位置的指针,该指针位于写入的最后一个字节之外一个字节。这样可以继续写入进程with perfect alignment of bytes,以便对内存块进行字符串连接。

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

答案 2 :(得分:3)

我正在复活这个老问题,因为答案并没有解释为什么 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));

答案 3 :(得分:0)

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

答案 4 :(得分:-2)

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