应该始终使用memcpy吗?

时间:2015-11-14 19:26:50

标签: c pointers memory memory-management

我正在使用C和手动内存管理并使用我的代码,我注意到了这一点:

假设我有

int *a = malloc(sizeof(int));
int *b = malloc(sizeof(int));
int c = 10;

如果我拿这些数字并执行此操作:

*a = c;

然后a将指向内存中与c分开的不同位置,但其值为c。如果我用过:

memcpy(a, &c, sizeof(int)); 

同样的事情会发生。不同的指针,相同的值。

我的问题是一个人是否比另一个更好?我知道char *通常使用的是memcpystrcpy,但是对于整数来说呢?一般指针怎么样?作业是否正常?

P.S。 我也知道

a = &c;

会使a指向与c相同的内存位置,因此有其值,但我认为这样会在a free之后留下一个悬挂指针永远不会在a的内存中调用,所以我不会使用它。

3 个答案:

答案 0 :(得分:5)

在您的示例中,您应该使用*a = c;,因为您只想复制单个值。 如果需要复制数组的多个连续元素,请使用memcpy

答案 1 :(得分:3)

具体实施。一些编译器(包括GCC)能够很好地优化(至少gcc -O2),调用标准函数memcpymemset(作为我以前的同事) Pascal Cuoq评论说,可能内联高效的分配机器代码);有时,GCC甚至可以优化某些结构的赋值,因为对memcpy的调用(有时,调用高效memcpy例程对于足够大的struct来说更快,包括结构赋值;在在其他情况下,通过某些memcpy转换的对__builtin_memcpy的调用被内联为一个有效的赋值代码,甚至可以通过寄存器而不使用任何内存)

您可以使用foo.c编译gcc -fverbose-asm -O2 -march=native -S foo.c示例,然后查看生成的foo.s

因此,如果您使用最近的 GCCClang/LLVM编译器(或其他一些好的编译器)并启用优化,那么您应该使用memcpymemset ...

换句话说,memcpy(a, &c, sizeof(int));可以像*a = c;一样有效地进行优化(如果您定义一个"类型泛型"宏,例如使用C99中的_Generic,会使用memcpy并且应该有效地进行优化。

答案 2 :(得分:0)

  

是否应该始终使用memcpy?

简单明了,没有

编写代码的第一个目标是使其易于理解和维护。当*a = c被声明为指向int的指针并且a被声明为int时,每个人都知道c会做什么。编译器也确切地知道你的意思。您永远不会看到编译器优化您的*a = c来调用memcpy,因为这将是一种不优化。

*a=c类型为memcpy时,您会看到编译器优化c来调用struct AVeryLargeStruct,并且a是指向该*a=c的指针。没有必要将memcpy(a,&c, sizeof(c))转换为*a=c,因为编译器会为您执行此操作,免费提供。写memcpy因为它比memcpy更容易出错,更不容易出错。

有些地方您确实需要使用memmove(或memcpy):

  • 复制数组
  • 在不使用工会的情况下输入双关语,
  • 复制到不正确对齐的内存中。

首先是标准操作程序;阅读您的代码并在该上下文中使用memcpy时,没有人会感到震惊。后两者不是SOP。在该上下文中memcpy的用法将使读者暂停代码。这是一件好事,因为你在那里做了一些有点棘手的事情。将memcpy隐藏在memcpy之中的那些棘手的电话隐藏在memcpy,您可以使用普通的任务,这使得您绝对需要使用command的几个地方无法脱颖而出。只有你的目标是赢得IOCCC,这才是一件好事。

如果您在任何地方使用command.ExecuteNonQuery(); ,那么您可能会使代码速度变慢,并且您更有可能让其他人认为您的代码存在问题。