When should I pass or return a struct by value? When should I pass or return a struct by value? c c

When should I pass or return a struct by value?


My experience, nearly 40 years of real-time embedded, last 20 using C; is that the best way is to pass a pointer.

In either case the address of the struct needs to be loaded, then the offset for the field of interest needs to be calculated...

When passing the whole struct, if it is not passed by reference,then

  1. it is not placed on the stack
  2. it is copied, usually by a hidden call to memcpy()
  3. it is copied to a section of memory that is now 'reserved' and unavailable to any other part of the program.

Similar considerations exist for when a struct is returned by value.

However, "small" structs, that can be completely held in a working register to twoare passed in those registersespecially if certain levels of optimization are usedin the compile statement.

The details of what is considered 'small'depend on the compiler and the underlying hardware architecture.


On small embedded architectures (8/16-bitters) -- always pass by pointer, as non-trivial structures don't fit into such tiny registers, and those machines are generally register-starved as well.

On PC-like architectures (32 and 64 bit processors) -- passing a structure by value is OK provided sizeof(mystruct_t) <= 2*sizeof(mystruct_t*) and the function does not have many (usually more than 3 machine words' worth of) other arguments. Under these circumstances, a typical optimizing compiler will pass/return the structure in a register or register pair. However, on x86-32, this advice should be taken with a hefty grain of salt, due to the extraordinary register pressure a x86-32 compiler must deal with -- passing a pointer may still be faster due to reduced register spilling and filling.

Returning a structure by value on PC-likes, on the other hand, follows the same rule, save for the fact that when a structure is returned by pointer, the structure to be filled out should be passed in by pointer as well -- otherwise, the callee and the caller are stuck having to agree on how to manage the memory for that structure.


Since the argument-passing part of the question is already answered, I'll focus on the returning part.

The best thing to do IMO is to not return structs or pointers to structs at all, but to pass a pointer to the 'result struct' to the function.

void sum(struct Point* result, struct Point* a, struct Point* b);

This has the following advantages:

  • The result struct can live either on the stack or on the heap, at the caller's discretion.
  • There are no ownership problems, as it is clear that the caller is responsible for allocating and freeing the result struct.
  • The structure could even be longer than what is needed, or be embedded in a larger struct.