Passing & returning large objects
But now consider user-defined types. If
you create a class and you want to pass an object of that class by value, how is
the compiler supposed to know what to do? This is not a type built into the
compiler; it’s a type you have created.
To investigate this, you can start with a
simple structure that is clearly too large to return in
registers:
//: C11:PassingBigStructures.cpp
struct Big {
char buf[100];
int i;
long d;
} B, B2;
Big bigfun(Big b) {
b.i = 100; // Do something to the argument
return b;
}
int main() {
B2 = bigfun(B);
} ///:~
Decoding the assembly output is a little
more complicated here because most compilers use “helper” functions
instead of putting all functionality inline. In main( ), the call to
bigfun( ) starts as you might guess – the entire contents of
B is pushed on the stack. (Here, you might see some compilers load
registers with the address of the Big and its size, then call a helper
function to push the Big
onto the stack.)
In the previous code fragment, pushing
the arguments onto the stack was all that was required before making the
function call. In PassingBigStructures.cpp, however, you’ll see an
additional action: the address of B2 is pushed before making the call,
even though it’s obviously not an argument. To comprehend what’s
going on here, you need to understand the constraints on the compiler when
it’s making a function call.