can anybody explain me the difference b/w call by reference and ...
As others have already said, C does not have "by-reference"
parameters.
The real key to understanding this is that the various "by-*"
mechanisms, as found in different programming languages, reflect
the *usage* of parameter names in the *source code* in those
languages.
Suppose, for instance, we do this, in some unspecified language
whose syntax sort-of-resembles C:
procedure foo(int: ax, ay) {
ax <- ay;
ay <- 0;
}
procedure main() {
int: x, y;
x <- 40;
y <- 42;
foo(x, y);
print(x, y);
}
suppose we compile and run this and the output is:
42 0
We can infer from this that this language probably uses one of
three parameter-passing mechanisms: by-reference, by-name, or
"value-result". We can do this because, without any special syntax,
foo() was able to modify main()'s x and y (though they are called
ax and ay in foo()). There are four common parameter-passing
mechanisms: the three I just named, and "by-value". The last
one does not permit such modifications.
The way to tell by-reference from by-name and value-result is
to do something trickier. This time, we compile, e.g.:
int global <- 99; // global variable, initially 99
procedure foo(int: ax) {
print("before changing ax:", ax, global);
ax <- 42; // sets ax to 42, but does it affect "global"?
print("after changing ax:", ax, global);
}
procedure main() {
foo(global);
print("after calling foo:", global);
}
If we compile and run this, we might expect:
before changing ax: 99 99
after changing ax: 42 42
after calling foo: 42
This is what we will get from either by-reference or by-name. The
call in main() passes something that *refers to* the global variable
(either its name, which the system looks up somehow each time, or
a reference -- which in the end is just a pointer) and each use of
the parameter fetches or changes the actual global variable. Thus,
when foo() looks at the global variable using the name "global",
it sees the new value (42) just stored into it by its temporary
alias ("ax").
But if we see instead:
before changing ax: 99 99
after changing ax: 42 99
after calling foo: 42
then what we actually have is "value-result": main() passed the
*value* of the global variable to foo(); foo() modified a *copy*
(so the global variable remained 99); but then upon returning,
main() took the new, adjusted result back (so the global variable
became 42, to match the change to the parameter). The call passes
the value, then -- later -- takes the result, hence its name.
(Distinguishing by-name from by-reference is hardest. The canonical
method is to pass both i and a
, and observe whether changes to
the passed-in "i" cause the other parameter to refer to the *new*
a. Since this is confusing, and call-by-name is quite rare,
I will omit this one entirely.)
Note that in a language like Pascal or C++, where reference parameters
*do* exist, no special syntax is required to *use* them (only to
declare them):
{ pascal }
procedure refparam(var x : integer);
begin
x := 42; { note: just plain "x" }
end;
// C++
void refparam(int& x) {
x = 42; // note: just plain "x"
}
But when you "fake" a reference parameter by passing a pointer
value by-value, as in C, you must then (a) "decorate" uses of that
pointer, and (b) also decorate the calls that will pass the pointer:
/* C */
void fakeref(int *x) {
*x = 42; /* note, "*x" not just "x" */
}
void func(void) {
int localvar;
...
fakeref(&localvar); /* note, "&localvar" not just "localvar" */
}
At its heart, the difference between "faking" by-reference using
pointer values in C, and true by-reference as found in other
languages, is just this syntactic decoration -- nothing less and
nothing more. But there are consequences to the "mere" syntax.
If we have to write "*x" in fakeref(), that gives us the opportunity
to write "x" without the "*":
void fakeref(int *x) {
*x = 42;
x = &othervar; /* changes x, not *x */
*x = 99; /* no longer changes func()'s "localvar" */
}
If we use the language's reference parameters (as in Pascal or
C++), we lose the opportunity to change "where x points". This
has both drawbacks and benefits: it is neither "good" nor "evil",
merely "different".