Array Parameters
The concepts of passing arrays as parameters follows from the
underlying philosophy of arrays in C. In order to understand array
parameters, it helps to first review the mechanisms available for
passing simple types (e.g., ints, doubles)
to functions in C. To that end, please review Chapter 9 of King, and/or the summary from the reading on pointers.
Array Parameters
In C, the declaration
double numberArray [5] = {43.7, 23.1, -56.2, 98.6, -40.0};
allocates space for 5 double
precision numbers and initializes those values. The
variable numberArray refers to the address of the
first array element.
From a compiler's perspective, a reference to the
variable numberArray usually is equivalent to the
expression &numberArray[0]. (Documentation lists
three exceptions, which we won't go into now.)
Because numberArray is actually an address, parameter
passage for arrays involves the base address of the
array—without specifying a ampersand &, the
base address of the array is passed to the function.
As an example, consider the following code:
/* illustration of passing an array parameter */
#include
/* Function that demonstrates an array parameter whose values are printed,
* modified, and printed again */
void
arrayFunction (double arrayParam[])
{
int i;
printf ("values of array at start of function: ");
for (i = 0; i < 5; i++)
printf ("%8.2lf", arrayParam[i]);
printf ("\n");
arrayParam[1] += 100;
arrayParam[3] += 300;
printf ("values of array at end of function: ");
for (i = 0; i < 5; i++)
printf ("%8.2lf", arrayParam[i]);
printf ("\n");
} // arrayFunction
/* Declare and initialize an array, pass to a function and print the result */
int
main (void)
{
double numberArray [5] = {43.7, 23.1, -56.2, 98.6, -40.0};
arrayFunction (numberArray);
printf ("values of array at end of main: ");
for (int k = 0; k < 5; k++)
printf ("%8.2lf", numberArray[k]);
printf ("\n");
return 0;
} // main
When this program is run, initial values are stored in
the numberArray array. When
function arrayFunction is called, the base address of
the numberArray array is copied to
the arrayParam parameter, but the values within the are
are not copied. Thus, array references within
the arrayFunction function refer to the original array
— there is not another copy of the array.
The resulting output from this program follows:
values of array at start of function: 43.70 23.10 -56.20 98.60 -40.00 values of array at end of function: 43.70 123.10 -56.20 398.60 -40.00 values of array at end of main: 43.70 123.10 -56.20 398.60 -40.00
Note that the changes to array elements 2 and 4, made within the function, are recorded in the main array.
Observation
As a secondary observation, note that an array variable
(e.g., numberArray) contains information about where the
array begins. However, the array does NOT contain information about
how long it is or where it stops. Thus, in the sample program, the
programmer had to remember that numberArray was declared
with 5 elements, and this information was hard coded into the program
in both arrayFunction and main.
If a function will be called with a variety of arrays given as the parameter value, it is common for an extra parameter (the array length) to be added, so the function will know how many array elements might be involved in processing.
#define
versus const int
Up to this point, we have preferred to use
the const keyword to declare constant
values in our programs. That's because a type gets clearly associated
with those names, and we can then rely on the compiler to use this
information (often to keep the programmer from overlooking type-related
mistakes).
However, in this reading we have intentionally made use
of the preprocessor
directive #define to denote the
fixed length of an array. Why?
The difference is subtle, and ever-so-slightly beyond the scope of this course, but suffice it to say that the preprocessor changes your code before it gets to the compiler, leaving a literal constant value in place of the defined name. In other words, the following code
#define LENGTH 5
double array[LENGTH];
gets changed by the preprocessor so that the compiler only sees
double array[5];
The compiler can therefore allocate a fixed amount of space for
the array in a stack frame where that variable is
declared. If we instead write
const int LENGTH = 5;
double array[LENGTH];
the result is subtly different. Because the compiler can
interpret LENGTH as a variable, the result may be what is
called a variable length array (VLA). In these cases, the length of the array is
not known at compile time so stack frame size becomes dynamic, which
can sometime cause in lower-level inefficiencies.