Even with a simple-minded translation into different generated code, stepping through a one-
dimensional array is often no faster with a pointer than with a subscript. Scaling needs to be done
when striding through consecutive memory locations with a pointer or an array. Scaling is done by
multiplying the offset by the size of an element; the result is the true byte offset from the start of the
array. The scaling factor is often a power of 2 (e.g., 4 bytes to an integer, 8 bytes in a double, etc.).
Instead of doing a slow multiplication, the scaling can be done by shifting left. A "shift-left-by-three"
is equivalent to multiplying a binary number by eight. If you have array elements the size of which
isn't a power of two (e.g., an array of structs), all bets are off.
However, striding down an int array is an idiom that's easily recognized. If a good optimizing
compiler does code analysis, and tries to keep base variables in fast registers and to recognize loop
paradigms, the end result may be identical generated code for pointers and array accesses in a loop.
Pointers are not necessarily any faster than subscripts when processing one-dimensional arrays. The
fundamental reason that C treats array subscripts as pointer offsets is because that is the model used by
the underlying hardware.
Rule 3 An "Array Name as a Function Parameter" Is a Pointer
Rule 3 also needs explaining. First, let's review some terminology laid down in Kernighan and Ritchie.
Term Definition Example
Parameter is a variable defined in a function definition
or a function prototype declaration. Some
people call this a "formal parameter."
int power( int base, int n);
base and n are parameters.
Argument is a value used in a particular call to a
function. Some people call this an "actual
parameter."
i = power(10, j); 10 and j are
arguments. The argument can be different
for the different calls of a function.
The standard stipulates that a declaration of a parameter as "array of type" shall be adjusted to "pointer
to type". In the specific case of a definition of a formal function parameter, the compiler is obliged to
rewrite an array into a pointer to its first element. Instead of passing a copy of the array, the compiler
just passes its address. Parameters that are functions are similarly treated as pointers, but let's just stick
with arrays for now. The implicit conversion means that
my_function( int * turnip ) {...}
my_function( int turnip[] ) {...}
my_function( int turnip[200]){...}
are all completely equivalent. Therefore, my_function() can quite
legally be called with an array, or really with a pointer, as its actual
argument.
Why C Treats Array Parameters as Pointers
The reason arrays are passed to functions as pointers is efficiency, so often the justification for
transgressions against good software engineering practice. The Fortran I/O model is tortuous because
it was thought "efficient" to re-use the existing (though clumsy and already obsolete) IBM 704
assembler I/O libraries. Comprehensive semantic checking was excluded from the Portable C
Compiler on the questionable grounds that it is more "efficient" to implement lint as a separate