"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