C中的memcpy和等号之间的效率差异是什么?

What's the efficiency difference between memcpy and equal sign in C?

我经常使用 memcpy 在 C/C++ 中复制结构。 我看到有人用等号直接copy struct in C/C++。 例如:

struct A { char* name; int value; };
struct B { struct A happy[10]; }; 

struct A a1, a2;
struct B b1, b2;
memcpy(&a1, &a2, sizeof(struct A));
b1 = b2;

memcpy 和等号的效率有什么区别?

C != C++...假设 C 情况下,您不能重载赋值运算符。

您的测试用例的 clang 输出值得一看:

struct A { char* name; int value; };
struct B { struct A happy[10]; }; 

void foo() {
  struct A a1, a2;
  struct B b1, b2;
  memcpy(&a1, &a2, sizeof(struct A));
  b1 = b2;
}

运行 以下命令使 clang 输出 LLVM 字节码:

clang -S -emit-llvm foo.c -o -

输出

; Function Attrs: nounwind uwtable
define void @foo() #0 {
  %a1 = alloca %struct.A, align 8
  %a2 = alloca %struct.A, align 8
  %b1 = alloca %struct.B, align 8
  %b2 = alloca %struct.B, align 8
  %1 = bitcast %struct.A* %a1 to i8*
  %2 = bitcast %struct.A* %a2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %2, i64 16, i32 8, i1 false)
  %3 = bitcast %struct.B* %b1 to i8*
  %4 = bitcast %struct.B* %b2 to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %3, i8* %4, i64 160, i32 8, i1 false)
  ret void
}

有趣的是,在这两种情况下(调用 memcpy 或赋值运算符)都会生成对 @llvm.memcpy.p0i8.p0i8.i64 的调用!

C++

在 C++ 中,结构可以是普通的旧数据(C 类型)或复杂的 - 需要调用构造函数和复制构造函数。

memcpy 和 = 的区别在于 = 有效。

当 = 应用于复杂结构时,它会按照其规则复制每个成员。 当 = 应用于简单结构(普通旧数据或 POD)时,它会执行 "memcpy".

C

在 C 中最初不允许复杂的复制,所以一些旧代码会 memcpy 而不是使用 =。在 C 中,它们等同于相同的操作。

现在 c++ 标签已被删除,我们谈论的是 C 而不是 C++。

假设a1a2是相同struct类型的变量

memcpy(&a1, &a2, sizeof(struct A));

a1 = a2;

做同样的事情。

但是赋值运算符实际是否使用memcpy完全取决于编译器。