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