在C中将一个结构分配给另一个结构

时间:2014-09-07 14:26:44

标签: c

假设我有2个strutcures s1s2,每个包含10000个元素的数组。如果我将一个结构复制到另一个结构,如s1=s2,则循环从1到10000,然后再s1[i]=s2[i]。两种方法之间会有任何速度差异吗?如果是,那么请告诉哪一个更快,为什么?

2 个答案:

答案 0 :(得分:2)

执行摘要:

在我的编译器上,所有这些转换为对memcpy()类函数的调用。它们碰巧是不同的,但编译器或多或少地认识到所有这些实现在功能上是相同的。

这些不同的memcpy()实现之间的性能差异可能很小。

代码:

#include <stdlib.h>
#include <string.h>

struct S {
    int x[10000];
};

void impl1(struct S *x, struct S *y) __attribute__((noinline));
void impl1(struct S *x, struct S *y) {
    *x = *y;
}

void impl2(struct S *x, struct S *y) __attribute__((noinline));
void impl2(struct S *x, struct S *y) {
    memcpy(x, y, sizeof(*x));
}

void impl3(struct S * restrict x, struct S * restrict y) __attribute__((noinline));
void impl3(struct S * restrict x, struct S * restrict y) {
    for (int i=0; i<10000; ++i)
        x->x[i] = y->x[i];
}

int main() {
    struct S x, y;
    impl1(&x, &y);
    impl2(&x, &y);
    impl3(&x, &y);
}

结果LLVM代码

define void @impl1(%struct.S* nocapture %x, %struct.S* nocapture readonly %y) #0 {
  %1 = bitcast %struct.S* %x to i8*
  %2 = bitcast %struct.S* %y to i8*
  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %1, i8* %2, i64 40000, i32 4, i1 false), !tbaa.struct !1
  ret void
}

define void @impl2(%struct.S* %x, %struct.S* %y) #0 {
  %1 = bitcast %struct.S* %x to i8*
  %2 = bitcast %struct.S* %y to i8*
  %3 = tail call i64 @llvm.objectsize.i64.p0i8(i8* %1, i1 false)
  %4 = tail call i8* @__memcpy_chk(i8* %1, i8* %2, i64 40000, i64 %3) #1
  ret void
}

define void @impl3(%struct.S* noalias nocapture %x, %struct.S* noalias nocapture readonly %y) #0 {
  %x2 = bitcast %struct.S* %x to i8*
  %y3 = bitcast %struct.S* %y to i8*
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x2, i8* %y3, i64 40000, i32 4, i1 false)
  ret void
}

编译器信息

[10:04am][wlynch@watermelon /tmp] clang -v
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

答案 1 :(得分:0)

我认为编译器为表达式s1 = s2生成的代码将比明确使用用户定义的循环更快。编译器很可能会使用stnadard C函数memcpy

相关问题