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++。
假设a1
和a2
是相同struct
类型的变量
memcpy(&a1, &a2, sizeof(struct A));
和
a1 = a2;
做同样的事情。
但是赋值运算符实际是否使用memcpy
完全取决于编译器。
我经常使用 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++。
假设a1
和a2
是相同struct
类型的变量
memcpy(&a1, &a2, sizeof(struct A));
和
a1 = a2;
做同样的事情。
但是赋值运算符实际是否使用memcpy
完全取决于编译器。