When you pass a struct by value how is it
suppose to be handled internally?
[/QUOTE]
However the compiler wants to.
Indeed.
There are only two commonly-used mechanisms, though: either the
caller makes a copy, or the callee makes a copy.
One of the two must do so unless the compiler can guarantee that
"not making a copy" is indistinguishable to the program from "making
a copy". That includes things like ¶m != &orig, e.g.:
#include <stdio.h>
struct S { int a[1000]; };
void f(void);
void g(struct S);
static struct S *some_s;
void f(void) {
struct S localvar;
some_s = &localvar;
g(localvar);
}
void g(struct S arg) {
if (some_s == &arg)
puts("aha, compiler failed to copy it!");
else
puts("compiler apparently made a copy");
}
int main(void) { f(); return 0; }
If neither f() nor g() copies localvar, g() will detect the
compiler's failure -- unless the compiler is REALLY clever and
changes the if to "if (0)" even though some_s == &arg.
Normally this sort of optimization -- avoiding the copy, then
rewriting comparisons to pretend the pointers are not equal even
though they are -- is not even attempted. Experienced C programmers
know that the copy happens and is expensive, so they avoid paying
the price by passing &localvar instead. This relieves some of the
pressure on compiler-writers, who can say: "Ah, well, no experienced
programmer would code it that way without good reason, so there is
no reason for me to bother trying to optimize it." This then feeds
back into programmers' experience: copies are expensive, so that
experienced programmers do not make them, so that compilers do not
optimize them, so that programmers do not make them, so....
(Implementations that have stacks often, but not always, have
"caller makes the copy" rules, even though "callee makes the copy"
tends to be more efficient. In particular, compilers that use a
callee-copies rule can remove the copy using nothing but simple
local information: if the copy's address is never taken and the
copy is never modified, the copy need not be made. In other words,
if g() secretly gets a "struct S *argp", all "arg.foo"s can become
"argp->foo"s if there is no &arg and no arg.foo=val. Otherwise,
g() can have a local "arg" variable and do "arg = *argp" and all
will be fine.)