在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与bare +运算符进行比较,显然后者更快,因为它没有函数调用开销)
我想我在问,“拳击”原始类型是一个元素结构有没有任何开销,但是使用该结构作为值类型。 (即我不是在调用malloc并使用指针,就像拳击在Java中一样。)
答案 0 :(得分:4)
我在-O2。(/ p>)用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
鉴于此,我不会过分担心这样做带来的额外开销。