Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!usc!ucsd!pacbell.com!ames!haven!mimsy!chris From: chris@mimsy.umd.edu (Chris Torek) Newsgroups: comp.lang.c Subject: Re: How do you declare a pointer to a two dimensional array? Keywords: explanation with PICTURES :-) Message-ID: <27610@mimsy.umd.edu> Date: 12 Nov 90 06:51:03 GMT References: <9197@aggie.ucdavis.edu> <16580@netcom.UUCP> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 122 In article <16580@netcom.UUCP> avery@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 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@cs.umd.edu Path: uunet!mimsy!chris