In C, a typedef doesn't grant you any additional type safety. You can use the the new type any place you can use the old type. Sometimes that's what I want, and sometimes it is not. Sometimes I want the compiler to warn me if I misuse my new type.
To make that happen, I sometimes do something like this:
typedef struct {
int value;
} NewType;
NewType doSomethingNT(NewType a, NewType b) {
return a.value + b.value;
}
Compared to:
int doSomethingI(int a, int b) {
return a + b;
}
(That plus is just an example. Let's assume that either there's a function call overhead in both cases, or else I ask the function to be inlined in both cases. But let's not compare doSomethingNT to the bare + operator, obviously the latter is faster because it doesn't have the function call overhead)
I guess I'm asking, is there any overhead in "boxing" a primitive type a one element struct, but using that struct as a value type. (I.e. I'm not calling malloc and using pointers to it like how boxing works in Java.)
On runtime level there is no difference between structs and classes in C++ at all. So it doesn't make any performance difference whether you use struct A or class A in your code.
No. Struct does not add any size, or have any overhead in the compiled C. It is a layer of syntax that requires additional work by the compiler, but has no overhead at runtime.
I tried this with the clang (specifically Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
) at -O2.
The source:
#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);
}
The compiler foiled my plan slightly—the generated main never calls add, instead computing the result at compile-time:
_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
It did generate an add function though! It takes its arguments in registers and returns a result in a register. The wrapper struct disappears completely in the compiler output, at least for this trivial case:
_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
Given that, I wouldn't worry too much about extra overhead from doing this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With