Functions with Arguments
Functions are an integral part of coding within the C language. An entire
system can be coded with functions that have no parameters (arguments),
relying instead on global variables and return types. However, this type of
approach seriously impacts the reusability, maintainability and clarity
of the code as it is not obvious what functions affect what variables. A
much neater and more flexible approach is to use functions with arguments
as this allows modular, recursive, externalised code to be developed.
Functions can receive their arguments in 2 ways
the difference is great and must be understood to get the most out of
functions with arguments.
Pass by Value
Pass by value arguments are simple. Consider the following code:
int y;
int inc_by_10(int a)
{
a = a + 10;
return a;
}
...
y = 5;
y = inc_by_10(y);
...
Most definitely a very trivial function but it serves to illustrate the
point, all that the function does is to use whatever value was
contained in the int argument a, add 10 to it and
return that value back as an int. So in this case we assign
the value 5 to y and then use y as the argument to
the function, assigning the return value back to y again.
An expensive way to add 10. If we had assigned the return value to a
variable other than y the value of y would not have
changed.
This is because we used a pass by value argument, that is, an argument
that contains a directly usable value. The value of y is
copied into the function argument a which has no relationship
to y at all except that they contain the same value. This means
that when the function manipulates a it is using a totally separate
variable from y and therefore y remains untouched.
Pass by Reference
The C language does not really have pass by reference arguments in the
true sense unlike PASCAL, Fortran or Visual Basic for example. Languages
that do have pass by reference arguments actually do some work for you
in the background to make the mechanism work. However, C does allow
you to implement the mechanism yourself in order to get pass by reference
arguments.
So what is a pass by reference argument. Well, it is an argument
that allows you to alter the value of the variable used as the argument.
Let us consider another version of the inc_by_10 function:
int y;
int inc_by_10(int *a)
{
*a = *a + 10;
return *a;
}
...
y = 5;
y = inc_by_10(&(y));
...
Notice the slight differences in the function. Instead of using a
straight int we now use an int * (a pointer to an
int) as the argument. This means that we must pass the address
of an int variable as the argument value. Yes we are
still really using pass by value, but in this case we do not want to
use that value directly, instead we treat it as a reference
to the real value. This means that whenever we want to get or set the
value of the argument we have to prefix it with a * character.
In order to change the value of the variable referenced in the argument,
y in this case, we did not have to re-assign the return value
of the function to it, as the first line of the function has already
changed the value. So we could re-write the example thus:
int y;
void inc_by_10(int *a)
{
*a = *a + 10;
}
...
y = 5;
inc_by_10(&(y));
...
and achieve the same effect. What languages like Visual Basic do for you is
to automatically take the address of the variable you specify as the argument
and pass that value to the function in the argument. Then they implicitly
dereference the address every time you use the argument in the function
body, just like we did explicitly in the example above.
That is all there is to pass by reference arguments, the trick is to remember
that they are actually pointers to variables.
|