Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!mcnc!rti-sel!dg_rtp!throopw From: throopw@dg_rtp.UUCP (Wayne Throop) Newsgroups: net.lang.c,net.micro.pc Subject: Re: double (*parray[15])[]; Message-ID: <367@dg_rtp.UUCP> Date: Tue, 27-May-86 17:01:21 EDT Article-I.D.: dg_rtp.367 Posted: Tue May 27 17:01:21 1986 Date-Received: Wed, 28-May-86 06:03:20 EDT References: <200@pyuxv.UUCP> <1181@ncoast.UUCP> <350@dg_rtp.UUCP> <3423@ukma.UUCP> <863@cyb-eng.UUCP> <1220@psivax.UUCP> Lines: 122 Xref: linus net.lang.c:8362 net.micro.pc:7987 > friesen@psivax.UUCP (Sarima (Stanley Friesen)) >> topher@cyb-eng.UUCP (Topher Eliot) >>There has been some debate on what the declaration >> double (*parray[15])[]; >>means. > The declaration declares an array of pointers to > entities of *undefined* size(not zero size). Right. > Due to the way pointer > arithmetic is defined in "C" this is not kosher(the compiler cannot > determine how much to add to the pointer). At least one compiler I > know of "accepts" this declaration by treating the unspecified arrays > as having size 1, thus making the declaration eqiuvalent to: > > double *parray[15]; /* Array of pointers to double */ No, no, no, no, no! (But almost yes. :-) First, the declaration double (*a[15])[]; is completely kosher, legal, proper, correct, loyal, honorable, brave, meaningful, trustworthy, and a fine declaration in its own right. Harbison and Steele (page 69) say The length of the array, a constant expression, may be omitted as long as it is not needed to allocate storage. It does *not* (I say, *NOT*) declare the same thing as double *a[15]; nor can any correct compiler for C take these two declarations to be equivalent. On the other hand, the expression (a[n]+m) *is* meaningless, since the size of the denotation type of the pointer expression a[n] is unknown, which is the problem Stanley points out above. Now, how do arrays of unknown size get along with pointer arithmetic? For array subscription to work, what must be known is the size of the *components* of the array, or the "inter-element spacing" (digression: size of an element is *not* the same thing as the inter-element spacing, but in C the latter can be deduced from the former by fiat (not renault, mind you, this only works for Italian cars :-)). The size of the containing array need not be known, only the lower bound (which is always zero in C). Thus, the "innermost" array descriptor (following a pointer declaration, or in a formal argument or external context) may be of unknown size. From this we see that as formal arguments or externals, these declarations are legal: int a[]; int b[][10]; int c[][10][10]; and these are not int d[10][]; int e[10][10][]; int f[10][][10]; and in any context, these declarations are legal int (*g)[]; int (*h)[][10]; int (*i)[][10][10]; (I will note that, despite the H&S quote above, the legitimacy of the (*)[] declaration with unknown size is not totally clear, but most compilers and typecheckers side with me on this.) Now then, the above is mostly the "no, no, no, no, no" part... what about the "almost yes" part? Well, it turns out that, due to the peculiar way pointer/array equivalence works in C, it is impossible to tell if a pointer-to-foo points to a single foo, or to an element of an array-of-foo, and therefore if what you want is a pointer which indicates an array-of-foo, it is often expedient to declare pointer-to-foo only, and have the array part be implicit via array-pointer equivalence. Note well that this notion does *not* make the two forms identical. Let's take these definitions: int *pi, (*pai)[]; For one example of non-equivalence, to reference "the nth int" via a pointer to int, one uses *(pi+n) or, equivalently pi[n] while with a pointer to array of foo, one uses (*pai)[n] Uttering "pi" in a value context yields the address of an int (or, implicitly, the address of the first in an unknown size array of int). Uttering "pai" in a value context yeilds the address of an array of int. The distinction between "address of array of int" and "address of the first element of an array of int" is very important to keep clear. The two are definitely *not* the same thing. (Trust me. But if you don't, it might help if you consider what happens when such a pointer is incremented.) The brevity of the "pi[n]" notation, and the practical equivalence in use of this to the "(*pai)[]" form, makes pointer-to-foo the normal way of talking about pointers to arrays in C. This does *not* mean that the distinction between these concepts is absent from C, however. -- "I would have *sworn* that *somebody* understood arrays in C!" --- overheard in the hallway -- "'Fiat' is Italian for 'hobby'." --- Eric Hamilton -- Wayne Throop !mcnc!rti-sel!dg_rtp!throopw