23

直到最近,我只看到使用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()普遍使用?

4

5 回答 5

35

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

至于为什么memcpy更受欢迎,我不确定。旧版本的 C 不支持结构分配(尽管早在 1978 年它就是一个常见的扩展),所以也许 memcpy 风格作为一种制作更可移植代码的方式被卡住了?无论如何,结构赋值在 PC 编译器中得到了广泛的支持,而且使用memcpy起来更容易出错(如果你弄错了大小,很可能会发生坏事),因此最好尽可能使用结构赋值。

但是,有些情况下仅memcpy适用。例如:

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

还要注意,尽管在 C 中memcpy和结构赋值通常是等价的,但在 C++ 中memcpy和结构赋值并不等价。一般来说,C++ 最好避免memcpying 结构,因为结构分配可以而且经常是重载以执行其他操作,例如深拷贝或引用计数管理。

于 2012-11-08T07:05:02.667 回答
6

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

我在解释我遇到的场景。

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

来自 Arm 网站:

指向目标位置的指针,比写入的最后一个字节高一个字节。这使得能够继续写入with perfect alignment of bytes内存块的字符串连接的过程。

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

于 2012-11-08T07:06:04.083 回答
5

我正在复活这个老问题,因为答案并没有解释为什么 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));
于 2016-01-06T09:13:07.837 回答
0

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

于 2014-03-31T14:18:29.503 回答
-2

在嵌入式平台上工作的人会更喜欢使用 memcopy 而不是直接分配结构。主要是在处理嵌入式平台时,有些编译器不支持直接结构赋值,需要用到memcopy。如果你在电脑上工作,那么这两种情况都没有问题,两者都是有效的。

于 2012-11-08T07:07:36.083 回答