5.8. Arrays, the & operator and function
We have already emphasized that in most cases, the name of an array is
converted into the address of its first element; one notable exception
being when it is the operand of sizeof , which is essential
if the stuff to do with malloc is to work. Another case is
when an array name is the operand of the & address-of
operator. Here, it is converted into the address of the whole
array. What's the difference? Even if you think that addresses would
be in some way ‘the same’, the critical difference is that they
have different types. For an array of n elements of type T, then the
address of the first element has type ‘pointer to T’; the address
of the whole array has type ‘pointer to array of n elements
of type T’; clearly very different. Here's an example of it:
int ar[10];
int *ip;
int (*ar10i)[10]; /* pointer to array of 10 ints */
ip = ar; /* address of first element */
ip = &ar[0]; /* address of first element */
ar10i = &ar; /* address of whole array */
Where do pointers to arrays matter? Not often, in truth, although of
course we know that declarations that look like multidimensional arrays
are really arrays of arrays. Here is an example which uses that fact, but
you'll have to work out what it does for yourself. It is not
common to do this sort of thing in practice:
int ar2d[5][4];
int (*ar4i)[4]; /* pointer to array of 4 ints */
for(ar4i= ar2d; ar4i < &(ar2d[5]); ar4i++)
(*ar4i)[2] = 0; /* ar2d[n][2] = 0 */
More important than addresses of arrays is what happens when you
declare a function that takes an array as an argument. Because of the
‘conversion to the address of its first element’ rule, even if you
do try to pass an array to a function by giving its name as an argument,
you actually end up passing a pointer to its first element. The usual
rule really does apply in this case! But what if you declare that the
function does have an argument whose type is ‘array of
something’—like this:
void f(int ar[10]);
What happens? The answer may suprise you slightly. The compiler looks
at that and says to itself ‘Ho ho. That's going to be a pointer when
the function is called’ and then rewrites the parameter type to be
a pointer. As a result, all three of these declarations are
identical:
void f(int ar[10]);
void f(int *ar);
void f(int ar[]); /* since the size of the array is irrelevant! */
Having seen that, your reaction might be to look for a solid object to
bang your head against for a while, but we don't recommend it. Take
a grip on yourself instead and put in the effort to work out:
- Why that is isn't really such a shock
- Why, given a function declaration like that, then within the
function, expressions of the form
ar[5] and so on work as
expected anyhow
Give that last one some thought. When you get to the bottom of it, you
really will have grasped what arrays and pointers are about.
|
Printer-friendly version
The C Book
This book is published as a matter of historical interest.
Please read the
copyright and disclaimer information.
GBdirect Ltd provides up-to-date training and consultancy in
C,
Embedded C,
C++
and a wide range of
other subjects based on
open standards if you happen to be interested.
|