C != C++... let's assume C case, where you cannot overload the assignment operator.
It's worth having a look to the output of clang for your test case:
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;
}
Running the following command makes clang output the LLVM bytecode:
clang -S -emit-llvm foo.c -o -
Which outputs
; 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
}
The interesting part is that in both case (call to memcpy or assign operator) a call to @llvm.memcpy.p0i8.p0i8.i64 is generated!