A struct can be either passed/returned by value or passed/returned by reference (via a pointer) in C.
The general consensus seems to be that the former can be applie
Note: reasons to do so one way or the other overlap.
When to pass/return by value:
int
, double
, pointer.The object is conceptually a smallish numeric
struct quaternion {
long double i,j,k;
}
struct pixel {
uint16_t r,g,b;
}
struct money {
intmax_t;
int exponent;
}
When to use a pointer to the object
Object needs memory management.
struct mystring {
char *s;
size_t length;
size_t size;
}
Notes: Recall that in C, nothing is truly passed by reference. Even passing a pointer is passed by value, as the value of the pointer is copied and passed.
I prefer passing numbers, be they int
or pixel
by value as it is conceptually easier to understand code. Passing numerics by address is conceptual a bit more difficult. With larger numeric objects, it may be faster to pass by address.
Objects having their address passed may use restrict
to inform the function the objects do not overlap.
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.