"array" vs. "&array" ?

Chris Torek chris at mimsy.umd.edu
Sun Dec 24 03:22:41 AEST 1989


In article <571 at mwtech.UUCP> martin at mwtech.UUCP (Martin Weitzel) writes:
>Some days ago I posted a question if it is legal (or makes sense)
>to write a "&" before an array. I received a few responses, some
>mentioned, that an "&" before an array is illegal and/or that the
>compiler simply ignores it.

This is the K&R-1 (`Classic C') interpretation.  In K&R-2/ANSI (`New C'),
& before an array name produces a value with a different type.

Given

	basetype arr[SIZE];	/* declares arr as `array SIZE of basetype' */

the type of `arr' is `array SIZE of basetype'.  In a value context,
such as the right hand side (but not the left side) of an assignment
operator, an object of type `array N of T' degenerates to a value of
type `pointer to T' whose value is the address of the 0'th element
of the object.  This is the same in both Classic C and New C.  As
the argument of the address-of operator `&', however, there is a
difference.  In Classic C, if the argument is an object of type
`array N of T', the `&' is ignored (with a warning), while in New C,
the result is instead a pointer to that object: a value with type
`pointer to array N of T' whose value is the address of the object.
Thus:

	arr

produces a value of type `pointer to basetype', value = &arr[0],
but

	&arr

produces either a warning (Classic C), or a value of type `pointer
to array SIZE of basetype' (New C).

>To my understanding, the following *is* a type mismatch:
>-----------------------------------------------------------------------
>main()
>{
>	char a[10], (*p)[10];
>
>	p = a;
>warning: illegal pointer combination, op =
>}

Yes, it is.  To make it correct (but require New C):

>	p = &a;

Unfortunately, when handed to an Old C compiler, you get:

>warning: & before array or function: ignored
>warning: illegal pointer combination, op =

>And to all of you who want to now, why I might want to do such strange
>things, look at the following:
>-----------------------------------------------------------------------
>main()
>{
>	char m[20][10], (*p)[10];
>
>	p =  m[0];
>	/*  ^ to "&" or not to "&", that is the question */

In both Classic and New C, this can be expressed as

	p = m + 0;

because `m' has type `array 20 of array 10 of char', and hence `m'
in a value context (such as an operand of `+') produces a value of
type `pointer to array 10 of char' whose value is the address of m[0].
In New C, of course, it can also be written

	p = &m[0];

since & accepts an object of type `array 10 of char' and produces a
value of type `pointer to array 10 of char' whose value is the address
of that object (m[0]).  It is just those darned Classic C compilers
that refuse to recognise this.

>	/* do something with (*p)[x] -- a single char
>	   and have the possibility to increment p to
>           point to the next group of 10 char-s */
>}
>-----------------------------------------------------------------------
>or another one:
>-----------------------------------------------------------------------
>char (*foo())[10]
>{
>	static char m[20][10] = {
>		/* some initialization */
>	};
>	int i;
>	/* do some calculations giving a value to i */
>	return  m[i];
>	/*     ^ to "&" or not to "&", that is the question */
>}

Again, `return m + i' is the only solution that works everywhere.

Incidentally, if you have PCC source, you can add `&arr' to your Classic
C compiler (the result is definitely an improvement) merely by *removing*
several lines of code.
-- 
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