[http://proquest.safaribooksonline.com/0131774298/ch09lev1sec3]
More about Arrays > Why C Treats Array Parameters as Pointers
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 program. That decision has been implicitly revoked by the enhanced error checking done by most ANSI C compilers.
The array/pointer equivalence for parameters was done for efficiency. All non-array data arguments in C are passed "by value" (a copy of the argument is made and passed to the called function; the function cannot change the value of the actual variable used as an argument, just the value of the copy it has). However, it is potentially very expensive in memory and time to copy an array; and most of the time, you don't actually want a copy of the array, you just want to indicate to the function which particular array you are interested in at the moment. One way to do this might be to allow parameters to have a storage specifier that says whether it is passed by value or by reference, as occurs in Pascal. It simplifies the compiler if the convention is adopted that all arrays are passed as a pointer to the start, and everything else is passed by making a copy of it. Similarly the return value of a function can never be an array or function, only a pointer to an array or function.
Some people like to think of this as meaning that all C arguments are call-by-value by default, except arrays and functions; these are passed as call-by-reference parameters. Data can be explicitly passed as call-by-reference by using the "address of" operator. This causes the address of the argument to be sent, rather than a copy of the argument. In fact, a major use of the address-of operator & is simulating call-by-reference. This "by reference" viewpoint isn't strictly accurate, because the implementation mechanism is explicit—in the called procedure you still only have a pointer to something, and not the thing itself. This makes a difference if you take its size or copy it.
How an Array Parameter Is Referenced
Figure 9-3 shows the steps involved in accessing a subscripted array parameter.
Figure 9-3. How a Subscripted Array Parameter Is Referenced
Note well that this is identical to Diagram C on page 101, showing how a subscripted pointer is looked up. The C language permits the programmer to declare and refer to this parameter as either an array (what the programmer intends to pass to the function) or as a pointer (what the function actually gets). The compiler knows that whenever a formal parameter is declared as an array, inside the function it will in fact always be dealing with a pointer to the first element of an array of unknown size. Thus, it can generate the correct code, and does not need to distinguish between cases.
No matter which of these forms the programmer writes, the function doesn't automatically know how many elements there are in the pointed-to thing. There has to be some convention, such as a NUL end marker or an additional parameter giving the array extent. This is not true in, for example, Ada, where every array carries around with it a bunch of information about its element size, dimensions, and indices.
func( int * turnip){...}
or
func( int turnip[]){...}
or
func( int turnip[200]){...}
int my_int; /* data definitions */
int * my_int_ptr;
int my_int_array[10];
you can legally call any of the function prototypes above with any of the following arguments. They are often used for very different purposes:
Actual Argument in Call | Type | Common Purpose |
---|---|---|
func(&my_int ); | Address of an integer | "Call-by-reference" of an int |
func( my_int_ptr ); | A pointer to an integer | To pass a pointer |
func( my_int_array ); | An array of integers | To pass an array |
func(&my_int_array[i] ); | Address of an element of int array | To pass a slice of an array |
Conversely, if you are inside func(), you don't have any easy way of telling which of these alternative arguments, and hence with which purpose, the function was invoked. All arrays that are function arguments are rewritten by the compiler at compiletime into pointers. Therefore, any reference inside a function to an array parameter generates code for a pointer reference. Figure 9-3<