Amir Saniyan
Amir Saniyan

Reputation: 13729

Does struct with a single member have the same performance as a member type?

Does struct with a single member have the same performance as a member type (memory usage and speed)?

Example:

This code is a struct with a single member:

struct my_int
{
    int value;
};

is the performance of my_int same as int ?

Upvotes: 11

Views: 3984

Answers (3)

chux
chux

Reputation: 153338

Agree with @harper overall, but watch out for the following:

A classic difference is seen with a "unstructured" array and an array in a structure.

char s1[1000];
// vs
typedef struct {
  char s2[1000];
} s_T;
s_T s3;

When calling functions ...

void f1(char s[1000]);
void f2(s_T s);
void f3(s_T *s);

// Significant performance difference is not expected.
// In both, only an address is passed.
f1(s1);
f1(s3.s2);

// Significant performance difference is expected.
// In the second case, a copy of the entire structure is passed.
// This style of parameter passing is usually frowned upon.
f1(s1);
f2(s3);

// Significant performance difference is not expected.
// In both, only an address is passed.
f1(s1);
f3(&s3);

Upvotes: 6

user743382
user743382

Reputation:

In some cases, the ABI may have specific rules for returning structures and passing them to functions. For example, given

struct S { int m; };
struct S f(int a, struct S b);
int g(int a, S b);

calling f or g may, for example, pass a in a register, and pass b on the stack. Similarly, calling g may use a register for the return value, whereas calling f may require the caller to set up a location where f will store its result.

The performance differences of this should normally be negligible, but one case where it could make a significant difference is when this difference enables or disables tail recursion.

Suppose g is implemented as int g(int a, struct S b) { return g(a, b).m; }. Now, on an implementation where f's result is returned the same way as g's, this may compile to (actual output from clang)

        .file   "test.c"
        .text
        .globl  g
        .align  16, 0x90
        .type   g,@function
g:                                      # @g
        .cfi_startproc
# BB#0:
        jmp     f                       # TAILCALL
.Ltmp0:
        .size   g, .Ltmp0-g
        .cfi_endproc


        .section        ".note.GNU-stack","",@progbits

However, on other implementations, such a tail call is not possible, so if you want to achieve the same results for a deeply recursive function, you really need to give f and g the same return type or you risk a stack overflow. (I'm aware that tail calls are not mandated.)

This doesn't mean int is faster than S, nor does it mean that S is faster than int, though. The memory use would be similar regardless of whether int or S is used, so long as the same one is consistently used.

Upvotes: 4

harper
harper

Reputation: 13690

If the compiler has any penalty on using structs instead of single variables is strictly compiler and compiler options dependent.

But there are no reasons why the compiler should make any differences when your struct contains only one member. There should be additional code necessary to access the member nor to derefence any pointer to such an struct. If you don't have this oversimplified structure with one member deferencing might cost one addtional CPU instruction depending on the used CPU.

Upvotes: 3

Related Questions