"array" vs. "&array" ?

Chris Torek chris at mimsy.umd.edu
Wed Jan 10 18:59:13 AEST 1990


In article <21621 at mimsy.umd.edu> I wrote more stuff about pointers
and arrays being quite different, except in a few special cases.

In article <2378 at ektools.UUCP> randolph at ektools.UUCP (Gary L. Randolph) writes:
>... the sentence in question is taken verbatim from Harbison and Steele,
>pg 273, section 11.6.4.

Since I do not have H&S (I should, if only for this sort of thing), I
canot guess why they might have put in an `... or pointer to pointer to'.

[me]
>>There are a few special cases under which an object of type `array
>>N of T' is converted to a value of type `pointer to T', and under which
>>a declaration of type `array N of T' is converted to a declaration of
>>type `pointer to T'.  This does not make the types equivalent.  They
>>are not interchangeable.

>Well, again I agree but then I am confused when I read, in K&R2, page 
>200 A7.1: 
>
>If the type of an expression or subexpression is "array of T," for
>some type T, then the value of the expression is a pointer to the
>first object in the array, and the type of the expression is altered
>to "pointer to T".

This must be mentally applied to `places where lvalues (object
designators) appear where values are desired'.  For instance, given

	T arr[N];

when

	p = arr;

appears, a value is desired, and the quoted sentence applies.

>They do not say that the above is true only for a few special cases.

It is an extremely common special case (values, i.e., expressions,
appear everywhere).  Nonetheless, it is a special case.

>Based on experience, I agree with Chris, but then I am confused when
>reading the above in two texts that I rarely question.

>Is the quote from Harbison and Steele wrong?

Not knowing the context, I canot say.

>Am I wrong in the inference from K&R that:
>
>float arrf[3] = {1.2,2.3,3.4};
>arrf;            /*evaluates to pointer to float according to K&R*/
>&arrf;           /*evaluates to pointer to pointer to float (my inference)*/

Yes, this is wrong.  `arrf', by itself, is in a value context: it
is a statement which evaluates to the value of `arrf'.  Thus, it
undergoes the change from

	[value context] <object, array 3 of float, arrf> ;

to

	[value context] <value, pointer to array 3 of float, &arrf[0]> ;

`&arrf', however, consists of two parts.  First there is a unary `&',
and its argument is examined in *object* context.  Here objects that
are arrays are *not* converted.  We have

	[value context] & [object context] <object, array 3 of float, arrf> ;

and the `&' is applied to an object of type array 3 of float, yeilding
a value (`&' produces values, not objects) of type `pointer to array 3
of float'.  Since this is a value, nothing further happens.

For comparison, when evaluating

	a = b;		/* assume a and b are `int' */

I would write:

	[value context] ( [object context] a = [value context] b ) ;

To evaluate the right hand side:

	[value context] <object, int, b>

and convert by the rule `an object that is not an array, when in value
context, becomes a value by replacing the object with its current value'.
(Classic C has some type extension rules here that New C defers until
actually required.)  So, if `b' has the value `42', we replace it with

	<value, int, 42>

and now we have

	[value context]
	  ( [object context] <object, int, a> = <value, int, 42> );

Since we have an object on the left hand side, and an object context,
we can do the assignment, setting `a' to 42.  Now we have

	[value context] ( [result of assignment to a] )

The result of an assignment is the value you would get if you examined
the assigned-to object: in this case the int-value 42, so it is a value
in a value context and all is well.

>Now I'm aware that if we look at a two dimensional array that if
>int arr[2][3];	/*for example*/
>then it is quite different to say
>
>&arr evaluates to pointer to array of int
>as opposed to
>&arr evaluates to pointer to pointer to int

(these are both wrong)

>since, in the first case, arr++ would increment sizeof(arr) and in the
>second case, arr++ would increment sizeof(pointer), which is not right.
>
>So how does page 200 of K&R apply here? Chris?

In Classic C, `&arr' is, as always, an error.  In New C, `&arr' produces
a value of type `pointer to array 2 of array 3 of int'.  Write it down
(this time I will leave out the [context] notations):

	a. for `int (*p)[2][3]; p = &arr':

	p = & <object, array 2 of array 3 of int, arr>

& takes object context, produces address of array as a value:

	p = <value, pointer to array 2 of array 3 of int, &arr>

`Evaluate' p:

	<object, pointer to array 2 of array 3 of int, p> =
		<value, pointer to array 2 of array 3 of int, &arr>

The types match, so the assignment is correct.  The object `p' is
given the address of `arr'.  `p++' adjusts p to skip over one
whole `array 2 of array 3 of int'.  On a byte-addressed machine, p++
adds 2*3*sizeof(int) to p.

	b. for `int (*q)[3]; q = arr;'

	q = <object, array 2 of array 3 of int, arr>

This time the object is in a value context (rhs of `=') so the rule
`object, array N of T, arr => value, pointer to T, &arr[0]' applies:

	q = <value, pointer to array 3 of int, &arr[0]>

Expand q:

	<object, pointer to array 3 of int, q> =
		<value, pointer to array 3 of int, &arr[0]>

The types match; q gets the given value.  `q++' adjusts q to skip
over one whole `array 3 of int'; on a byte-addressed machine, this
adds 3*sizeof(int).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list