<OT>
But for those of us who think in terms of "by reference", what is the
actual difference in passing an arg "by reference" or passing a pointer
to the arg? (Of course, ignoring the C compiler's lack of support for
"by reference").
</OT>
This might be better in comp.programming...
There are three common parameter-passing mechanisms for modern
languages: "by value", "by reference", and "value-result". (Algol's
old "by name" method, which is a little tougher to describe, is
hardly ever used because it is so weird.)
True "reference" or "value-result" methods require special compiler
treatment -- usually special syntax -- in which a given function
parameter is designed as such, and then used as if it were an
ordinary variable. One sees this in C++, for instance:
void fn(int &x) {
x = 3;
}
void h(void) {
int i;
fn(i);
/* now i == 3 */
...
}
In C, we have to "manually" simulate the reference argument by
explicitly noting each place at which an underlying pointer mechanism
is used:
void fn(int *x) {
*x = 3; /* note "*" in front of x */
}
void h(void) {
int i;
fn(&i); /* note "&" in front of i */
...
}
The syntax *is* the difference, in other words.
The difference between "reference" and "value-result" is a bit more
subtle. Suppose we have the following C++-like code:
int y = 1;
void fn(int &x) {
x = 3;
printf("at first, x = %d and y = %d\n", x, y);
y = 4;
printf("now x = %d and y = %d\n", x, y);
}
void h(void) {
fn(y);
printf("finally, y = %d\n", y);
}
What does this program fragment print? When we assign a new value
to x in fn(), does that *immediately* change the value of y? When
we assign a new value to y, does that *immediately* change the value
of x?
If we rewrite this in C with explicit pointers, the answers are
clear:
int y = 1;
void fn(int *x) {
*x = 3;
printf("at first, *x = %d and y = %d\n", *x, y);
y = 4;
printf("now *x = %d and y = %d\n", *x, y);
}
void h(void) {
fn(&y);
printf("finally, y = %d\n", y);
}
This program fragment must print:
at first, *x = 3 and y = 3
now *x = 4 and y = 4
finally, y = 4
In other words, both *x and y name the same underlying object,
and updates to EITHER ONE are immediately reflected in BOTH (in
the output).
If our C++-like language used value-result, however, we might
rewrite it in C like this:
int y = 1;
void fn(int *xptr) {
int x = *xptr;
x = 3;
printf("at first, x = %d and y = %d\n", x, y);
y = 4;
printf('now x = %d and y = %d\n", x, y);
*xptr = x;
}
void h(void) {
fn(&y);
}
This program fragment produces very different output, not just
because the "*"s are gone in front of each x:
at first, x = 3 and y = 1
now x = 3 and y = 4
finally, y = 3
In other words, the "final output" from x to *xptr only happens
when we exit the function fn(). The "initial copy" from *xptr to
x only happens when we enter the function. Hence the function fn()
"gets the value" and "returns the result", i.e., has "value-result"
semantics.
C avoids dealing with the issue of whether to use by-reference or
value-result by making the programmer use pointers explicitly.
Other languages define the result (e.g., C++) or leave it up to
the implementor (e.g., Fortran -- F77, at least, prohibits passing
a COMMON-block variable to a subroutine when the subroutine will
both write on the parameter *and* use the same COMMON variable,
since this "exposes the difference" between by-reference and
value-result).