【问题标题】:Should memcpy always be used?是否应该始终使用 memcpy?
【发布时间】:2016-02-16 04:41:13
【问题描述】:

我正在使用 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,但是对于整数呢?一般的指针呢?作业可以吗?

附: 我也知道

a = &c;

将使a 指向与c 相同的内存位置,因此具有它的值,但我想这会留下一个悬挂指针,a 所在的位置,因为free 永远不会在内存上调用@ 987654335@ 所以我不会使用它。

【问题讨论】:

  • *a = c; 没有任何函数调用开销
  • memcpy 一般只在不能正常赋值时使用,比如复制数组。

标签: c pointers memory memory-management


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 反之亦然,memcpy(a, &c, sizeof(int)); 之类的调用可能会优化为几条看起来像是从 *a = c; 生成的指令。
    • 你是说他们优化memcpy 比简单的分配更好?如果优化后的代码是等价的,为什么建议他们“应该使用memcpy”?
    【解决方案3】:

    应该一直使用 memcpy 吗?

    简单明了,没有

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

    c 的类型为struct AVeryLargeStruct 并且a 是指向相同的指针时,您将看到编译器将*a=c 优化为对memcpy 的调用。无需将*a=c 转换为memcpy(a,&c, sizeof(c)),因为编译器会为您执行此操作,免费。写*a=c,因为它比memcpy 更清晰,更不容易出错。

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

    • 复制数组,
    • 类型双关语,不使用联合,并且
    • 复制到或从不正确对齐的内存中复制。

    一是标准作业程序;没有人会在阅读您的代码并在该上下文中看到对memcpy 的调用时感到震惊。后两者不是SOP。在这种情况下使用memcpy 会让读者暂停阅读您的代码。这是一件好事,因为你在那里做的事情有点棘手。将那些对memcpy 的棘手调用隐藏在对memcpy 的数千个其他调用中,您可以在其中使用普通赋值,这使得您绝对需要使用memcpy 的少数地方不会脱颖而出。只有当你的目标是赢得 IOCCC 时,这才是一件好事。

    如果您在任何地方都使用memcpy,您可能会使您的代码变慢,甚至更有可能让其他人认为您的代码有问题。

    【讨论】:

      猜你喜欢
      • 2012-06-17
      • 2017-02-11
      • 2015-01-30
      • 1970-01-01
      • 1970-01-01
      • 2021-05-16
      • 2021-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多