How do you declare a pointer to a two dimensional array?

Chris Torek chris at mimsy.umd.edu
Mon Nov 12 17:51:03 AEST 1990


In article <16580 at netcom.UUCP> avery at netcom.UUCP (Avery Colter) writes:
>Well, any array, when referred to by name only without subscripts,
>translates into a pointer to the lowest element of the array,

In value contexts, yes;

>i.e. the location of spam[0][0].

no.  The declaration was `float spam[M][N];' for some constants M and
N.  The type of the object `spam' is thus `array M of array N of float'.
In a value context, this becomes a pointer to the first element of `the'
array.  Which array?---we have two `array of's above.

The answer is that it becomes a `pointer to array N of float'.  This
value is not an <object, array N of T> and therefore does NOT undergo
a second conversion.  The result is a pointer to first of the sub-arrays
that make up the array `spam'.  As I wrote before, this is

	float (*p)[N] = spam;

>However, at least on my machine, pointers don't take kindly to more
>than one dimension of indexing.

The result of `indexing' (which is in C a sham: e1[e2] does not really
`index' e1 `by' e2; instead, it adds e1 and e2 and indirects through
the result) a `pointer to T' is, if not an error, an object (lvalue) of
type T.  If each pointer points to one or more `int's, then ptr[value]
is a single int (or an error).

In this case, p points to one or more---in fact, it points to exactly M
---`array N of float's, so p[value] is an object of type `array N of
float'.  Since this *is* an array object, it goes through another of
those `array to pointer' conversions whenever it appears in a value
context, so p[v1][v2] is entirely legal and means to take the v1'th
`array N of float' at which p currently points, turn that object into
the address of the first of the N floats in that array, then take the
v2'th float at which the resulting pointer points:

			  0  1  2  ... N-1
	+---+		+------------------+
	| p |---------->| array N of float | p[0]
	+---+		+------------------+
			| array N of float | p[1]
			+------------------+
			|	 .	   |
			|	 .	   | ...
			|	 .	   |
			+------------------+
			| array N of float | p[M-1]
			+------------------+

`p' points directly *to* one `array N of float' (p[0]), but p points
*at* a whole passel of `array N of float's (p[0] through p[M-1]).  An
`array N of float' is slippery, though, and when you try to grab the
whole thing with p[0]:

	+---+		+------------------+
	| p |---------->| array N of float | p[0]
	+---+		+------------------+

you have to loosen your hold and you end up with a pointer to the first
one:

			  $   p[0] in value context
			  |
			  v
	+---+		+---+---+...+---+--+
	| p |---------->| array N of float | p[0]
	+---+		+------------------+

`$' is an intermediate value and is not (necessarily) actually stored
in memory anywhere in the computer (hence no box).  It points to a
single float (here p[0][0]) but it points `at' N floats (p[0][0]
through p[0][N-1]).  This means you can fetch `$[0]' (so to speak) to
get p[0][0], or `$[4]' to get p[0][4], and so on.  Of course `$' is not
a legal character in C, except inside string and character constants
and comments.

(In the picture above, p points *to* the entire `array N of float', but
`$'---p[0] taken as a value---points *to* only one float, hence the
extra `+' marks along the top.)

>So I resorted to making a separate array of pointers, and setting
>each of the elements of this array of pointers to match the addresses
>of each of the subarrays of the original.

[edited to be `array M of array N of float', etc]

>float spam[M][N];
>float *pointer[M];
>int index;
>for (index = 0 ;index < M; ++index)
>   pointer[index] = spam[index];

This is entirely legal, and amounts to copying each `$' into an actual
variable (pointer[index]) by placing each spam[index] computation in a
value context (the right hand side of the last `=').  Each spam[index]
is an `object, array N of float' and therefore is transformed into a
`value, pointer to float', which is proper to store in pointer[index].
The result is an array M of pointers, each pointing *to* one float but
`at' N floats:

				  0  ... N-1
	+--------------+	+---+---+---+
	|  pointer[0]  |------->|   |...|   | spam[0]
	+--------------+	+---+---+---+
	|  pointer[1]  |------->|   |...|   | spam[1]
	+--------------+	+---+---+---+
	|       .      |	| . |   | . |
	|       .      |	| . |...| . | ...
	|       .      |	| . |   | . |
	+--------------+	+---+---+---+
	| pointer[M-1] |------->|   |...|   | spam[M-1]
	+--------------+	+---+---+---+

Each pointer[i] points *to* the 0'th spam[i] (hence the extra `|'s
making each spam[x][y] a separate box, vs the diagram for `p' in which
each spam[x] was a single continuous box) but `at' the entire
`spam[i][0] through spam[i][N-1]'.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list