C language, old dog new trick - struct by value (RVO)

Status
Not open for further replies.

stevech

Well-known member
Maybe because way back, in C, on processors with a dearth of registers and RAM, I somehow learned that one cannot have a function return a struct by value.
I came across some code, first ever, that did so. Essentially it was

Code:
static  [B]myStructType_t[/B]  myFunc(void)  {
    [B]myStructType_t[/B] s;

   // .. code here alters s

  return s;
}
Presumably, the "static" declaration is n/a.

I wonder what happens when size of myStuctType_t is rather large?
The code I saw this in has a struct type that is 4 uint16_t
And returning a struct that is a local would creep-out most.

(C, not C++)
 
Last edited:
It depends on the target architecture, software ABIs for calling/passing results, and to some extent on the backend optimization efforts.

For most architectures/ABIs, GCC might return a structure that is the same size and alignment as one of the standard integer types like that integer type (typically in registers). Otherwise, GCC typically expects a hidden pointer to be passed as the first argument, and that pointer is an area large enough to hold the structure being returned. The function returning the structure would copy the result to the temporary.

Typically, the caller would call the function returning a structure would allocate a stack temporary big enough to hold the structure, and pass the address of the temporary as the first argument. After the function returns, it would then copy the temporary structure to the result. In some cases, such as having a local variable that is assigned the structure, the compiler can eliminate the copy, and just pass the address of the final variable.

Returning structures has always been somewhat inefficient, but it has been part of the C standard since the first ANSI (now ISO) C standard in 1989. At this stage, I don't remember if the original K&R definition of C allowed returning structures or not.
 
Damn I accidentally deleted my first reply...

This question most probably has a better and more thorough answer on stackoverflow, but here are my guesses:

The function doesn't return a pointer or reference (not in C, anyway) so it must return a copy of the local struct. In principle this is perfectly safe. If the struct is too large, it will simply blow up the stack. This is why returning struct types in this way is considered bad; an out-pointer should be passed as an argument instead. This is what compilers do for objects in C++.
 
Thanks... I see this used in many places in some code from a vendor. No caveats stated about the target MCU but in practice, they are all Cortex M0-M4 so far.
I use the IAR compiler for most work. With optimization off, I see in the debugger's assembler listing that the function returning the struct by value has code to deepen the stack enough for the struct to fit. Just before returning, it calls a memory copy for unaligned variables to put the result on the stack. In the usual case, it then returned the small struct in three registers and returned. I added 2KB to the struct to see what happens. The copy was still done but the return was not in registers. I need to study it more - don't quite get it now.

If I assume the author was not a moron, maybe the thought was that it was OK since the struct was just 3 or 4 shorts.

I think I'll continue my habit of call by reference for structs. The caller preserves the return for its own use anyway, in a global or its own local. So, maybe the author was indeed just a sloppy coder not used to C rather than C++.

PS: Sheepishly, I admit to learning K&R C before the ANSI standards.
 
Last edited:
Status
Not open for further replies.
Back
Top