2014-03-06 52 views
6

在C中,typedef不会授予您任何其他类型的安全性。你可以使用新类型的任何地方你可以使用旧类型。有时候这就是我想要的,有时不是。有时我希望编译器警告我,如果我滥用我的新类型。int和仅包含int的结构之间是否存在性能差异?

要做到这一点,我有时会做这样的事情:

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与bare +运算符进行比较,显然后者更快,因为它没有函数调用开销)

我想我问,有没有在“装箱”一个基本类型一个元素结构,但使用该结构作为值类型的任何开销。 (也就是说,我没有调用malloc并使用指针来指导它如何在Java中实现装箱效果)。

+1

唯一的开销是编译时间 – deviantfan

+0

Veeeerrrry类似于[c-class-wrapper-around-fundamental-types](http://stackoverflow.com/questions/17793298/c-class-wrapper-around-fundamental-types ),但这是关于C++ ... –

+2

这很有趣,但可能最好的答案是测量一些实际的程序,版本1使用普通类型,版本2使用你的“盒子类型”。可能优化器可以使版本2不低于版本1 – Brandin

回答

4

我试着在-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:         ## @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 

鉴于这种情况,我不会太担心从这样做额外的开销。

相关问题