Contributor's Corner

A collection of hopefully helpful information
Functionality Clarity Elegance

Pointers


Sneaky Pointers

An example of a sneaky pointer is an array that has apparently become a pointer while you weren't looking. If one passes an array (remember, arrays are represented by the address of their beginning element) as a parameter to a function, the array address gets copied to the stack as a pointer to the array. The parameters passed to a function are, for all practical purposes, local definitions within the function. The writer declares them with the declaration or definition of the function and initializes them with the call. They are merely separated from the other locals by some microprocessor overhead and bookkeeping values. Let me repeat that: The parameters passed to a function are, for all practical purposes, local definitions within the function. The writer declares them with the declaration or definition of the function and initializes them with the call. You may never have thought of it that way.

If one declares a function like this,

void someFunction (char theArray []);
and calls it like this,
char myArray [32]; 
... 
someFunction (myArray); 
One may just as well have declared it thusly:
void someFunction (char *theArray);
The compiler performs the translation. someFunction has no inkling of the size of the array which is being referred to. If the function needs size information, add another argument. If one increments theArray it will increment by the size of one element, in this case one byte (the size of a char). If one wishes to increment it beyond the array bounds, the compiler won't sense that and chastise one severely. One may wind up at run-time trotting off into the weeds and barfing on one’s shoes. Mama compiler does many favors, but she is not a psychic miracle worker. Similarly, if one declares the function like this,
void someFunction (char theArray [][5]);
the compiler infers (correctly) that theArray is a pointer to an array of arrays of five chars. The effect is the same as if coded like this:
char myArray [10][5]; 
char (*pArray)[5]; 
... 
pArray = myArray; 
someFunction (myArray); 
someFunction (pArray);
Note the definition of the pointer. The parentheses dictate that it is a 
pointer to a char array containing five chars, not an array of five char pointers. 
someFunction will behave in precisely the same way for both calls. If one increments theArray it will increment by five elements, the number of chars in each 'row'.

A definition such as this, if carried into multiple dimensions, allows one to use array notation inside the function in lieu of multiplying a bare element pointer by the size of lower dimensions. It is sufficient that it be clear to the compiler, by one declaration or another, what the various sizes are below the highest dimension. Regardless of the pointer type deduced by the compiler (element, row, layer, whatever), information concerning the total size of the array is lost! Observing the boundary limits is the responsibility of the programmer.

 Pointer ArithmeticThe NULL Pointer