How is a struct communicated when its sent by value if a function can only return a value that can fit in a register?
A function can return whatever is legal to return. However, only register-sized-or-smaller values can be used to implement the return
statement by the convention of leaving a value behind in a single register, for obvious reasons. Some implementations allow for representing large data types using more than one register; of course, this means that the caller has to be written to expect to examine multiple registers to get the full return value.
"What happens" at the machine level is not specified by the language standard, and depends on the particular compiler, its optimization capabilities, details of the architecture, etc. However, the straightforward implementation on ordinary platforms is to have the caller reserve space on the stack (so that it lasts beyond the cleanup) and have the callee write the data there. Since the allocation is static, typically the required space can simply be taken into account when computing the size of the stack frame for the caller. The implementation might silently generate a pointer and pass it to the callee in a register; or it might arrange that every caller puts this reserved space in the same place in its stack frame, such that the callee can add an offset to the stack pointer to determine where to write; or it might do some other thing that I'm currently not creative enough to think of.
There are any number of ways to handle communication of information between functions at the machine level, depending on both the machine and the language (although we are usually talking about either C or C++ when we have these discussions, since all the other popular choices either run on a VM, are interpreted or have some other fancy thing going on). The general term you want to look into is Application Binary Interface, or ABI.
long
if you want to see the pass by memory in action, or add more members to exceed 16 bytes. – Desiredesireastatic
functions, or private clones) that can't be called from code outside the current compilation unit; then compilers can in theory invent custom calling conventions if they don't simply inline. – Bloodletting