直到最近,我才看到用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()
?
答案 0 :(得分:29)
两种方法都是等效的,并执行浅拷贝。这意味着复制了结构本身,但不会复制结构引用的任何内容。
至于为什么memcpy
更受欢迎,我不确定。较旧版本的C不支持结构赋值(although it was a common extension as early as 1978),所以memcpy样式可能会成为制作更多可移植代码的方式吗?在任何情况下,PC编译器都广泛支持结构分配,并且使用memcpy
更容易出错(如果你的大小错误,可能会发生坏事),所以最好使用结构赋值可能的。
但是,只有memcpy
有效的情况。例如:
memcpy
,因为结构分配需要两者要正确对齐的来源和目的地。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,那么在任何一种情况下都没有问题,两者都是有效的。