【问题标题】:Is there a performance difference between an int and a struct containing only an int?int 和仅包含 int 的结构之间是否存在性能差异?
【发布时间】:2014-03-06 19:07:29
【问题描述】:

在 C 中,typedef 不会赋予您任何额外的类型安全性。您可以在任何可以使用旧类型的地方使用新类型。有时这就是我想要的,有时不是。有时我希望编译器在我误用我的新类型时警告我。

为了做到这一点,我有时会这样做:

typedef struct {
    int value;
} NewType;

NewType doSomethingNT(NewType a, NewType b) {
    return a.value + b.value;
}

相比:

int doSomethingI(int a, int b) {
    return a + b;
}

(那个加号只是一个例子。让我们假设在这两种情况下都有一个函数调用开销,或者我要求在这两种情况下内联函数。但是我们不要将 doSomethingNT 与裸 + 运算符进行比较,显然后者更快,因为它没有函数调用开销)

我想我在问,将原始类型“装箱”为单元素结构,但使用该结构作为值类型是否有任何开销。 (即我没有调用 malloc 并使用指向它的指针,就像 Java 中的装箱方式一样。)

【问题讨论】:

  • 唯一的开销是编译时间
  • Veeerrrry 类似于 c-class-wrapper-around-fundamental-types,但那是关于 C++...
  • 这很有趣,但最好的答案可能是测量一些实际程序,版本 1 使用普通类型,版本 2 使用您的“盒子类型”。可能优化器可以使版本 2 不比版本 1 慢
  • 测量这么小的变化可能很困难,因为如果有开销,它可能非常小。我认为回答这个问题的最好方法是将每个版本编译成汇编,看看有什么区别(如果有的话)。

标签: c performance struct int


【解决方案1】:

我在 -O2 用 clang(特别是 Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn))尝试了这个。

来源:

#include <stdio.h>

struct da_int {
    short i;
};

struct da_int add(struct da_int x, struct da_int y) {
    struct da_int rv = {x.i + y.i};
    return rv;
}

int main(int argc, char *argv[]) {
    struct da_int x = {5}, y = {3};
    printf("%d\n", add(x, y).i);
}

编译器稍微挫败了我的计划——生成的 main 从不调用 add,而是在编译时计算结果:

_main:                                  ## @main
    .cfi_startproc
## BB#0:
    pushq    %rbp
Ltmp7:
    .cfi_def_cfa_offset 16
Ltmp8:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp9:
    .cfi_def_cfa_register %rbp
    leaq    L_.str(%rip), %rdi
    movl    $8, %esi
    xorb    %al, %al
    callq    _printf
    xorl    %eax, %eax
    popq    %rbp
    ret
    .cfi_endproc

它确实生成了一个添加函数!它在寄存器中获取参数并在寄存器中返回结果。包装器结构在编译器输出中完全消失,至少对于这种微不足道的情况:

_add:                                   ## @add
    .cfi_startproc
## BB#0:
    pushq    %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    addl    %esi, %edi
    movw    %di, %ax
    popq    %rbp
    ret
    .cfi_endproc

鉴于此,我不会太担心这样做会产生额外的开销。

【讨论】:

    猜你喜欢
    • 2010-09-24
    • 1970-01-01
    • 2011-06-05
    • 1970-01-01
    • 2020-04-20
    • 2016-06-05
    • 2012-03-05
    • 1970-01-01
    相关资源
    最近更新 更多