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 []);
char myArray [32]; ... someFunction (myArray);
void someFunction (char *theArray);
void someFunction (char theArray [][5]);
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.
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