allbery@ncoast.UUCP (Brandon Allbery) (06/21/86)
Expires: Okay, I've another dumb question for everyone: In an application I wrote, I use pointers to arrays. Now: If the array is malloc'ed, the correct cast is: (struct foo (*)[]) and you assign the ``pointer to the array'' to a variable. But, if it's in initialized data, you can't do it that way: you can't take a ``pointer to an array''. So the cast is: (struct foo *) BUT: the arrangement in memory is identical! It should be even on tagged architectures, etc.; in fact, (struct foo *) is always wrong, and might conceivably cause problems on a tagged architecture if you're really pointing to an array. So: why isn't the correct type of an array name (struct foo (*)[])? That would make much more clear the meaning of the pointer, and would avoid many of the pointer-vs.-array confusions. --Brandon -- ihnp4!sun!cwruecmp!ncoast!allbery ncoast!allbery@Case.CSNET ncoast!tdi2!brandon (ncoast!tdi2!root for business) 6615 Center St. #A1-105, Mentor, OH 44060-4101 Phone: +01 216 974 9210 CIS 74106,1032 MCI MAIL BALLBERY (part-time)
throopw@dg_rtp.UUCP (Wayne Throop) (06/24/86)
> allbery@ncoast.UUCP (Brandon Allbery) > Okay, I've another dumb question for everyone: A-Hah! Not a dumb question at all! It is a question that cuts right to the center of the confusion about pointers in C. At least... the *second* part of your question is most insightful. I'm not at all sure what the first part of your question *is*. Let's examine the first part before we get to the insight later: There are two specific casts that are asked about, (struct foo (*)[]) and (struct foo *). As I understand it, the question is, where should each be used, and why. No specific examples of the use of either cast are given, but I conjecture from previous postings that the first cast is used like so: int (*a[N])[]; a[M] = (int (*)[]) malloc( (unsigned) O*sizeof(int) ); This is, of course, correct. The second cast's use is much more obscure... the only thing said about it is: > But, if it's in initialized data, you can't do it that way: > you can't take a ``pointer to an array''. > So the cast is: (struct foo *) Lacking an example of where this cast must be used, some questions immediately spring to mind. What "it" is in initialized data? The array or one of the the arrays pointed to? What "it" is it that "can't be done that way". The cast? The assignment (or maybe an initialization)? The malloc? Finally, what "way" is being talked about here? The format of the assignment/initialization? The method of allocating storage? Zen budhism? If the declaration is of an array of pointers to array of int, then there would be no pointer of type (int *) anywhere. (NOTE: no *pointer* of that type... there *would* be *addresses* of that type. (Using "pointer" to mean "an address lvalue".)) So, as I say, I have no idea what this part of your question is talking about. On the off chance that the first "it" is "one of the arrays pointed to", the and second "it" is "the malloc", I'd do *that* like so: int a1[O], (*a[N])[] = { ... (int (*)[])a1, ... }; Note however, this doesn't involve a cast to type (int *), so perhaps that wasn't what was meant? Anyhow, the insightful stuff follows: > BUT: the arrangement in memory is identical! Yes. The types (int *) and (int (*)[]) are refering to identical memory layouts. Note that they are *NOT* *NOT* *NOT* the same type just because they refer to identical memory layout. The *OPERATIONS* that may be performed on objects of these types are different. > So: why isn't the correct type of an array name (struct foo (*)[])? Let's ammend that slightly... "Why isn't the correct type of an int array name (int [])?" *GOOD* question. *VERY* good question. The answer is "just because". Or, if you want to be insulting, because DMR slipped a cog. This is *THE* *MOST* *CONFUSING* thing about C, by far. An array name, when evaluated, does *NOT* *NOT* *NOT* yield an array type. This is the single greatest lunacy of the C language. It might be argued that this is the *ONLY* great lunacy in C, although the declaration-mirrors-use rule probably ought to be considered a great lunacy as well. (In case you can't tell, these nasty remarks about array name evaluation in C are my opinions only, and only about 60% serious. Others differ with me. However, it is objective fact that this one point causes more confusion and error than any other construct in C. By far.) > That > would make much more clear the meaning of the pointer, and would avoid many of > the pointer-vs.-array confusions. Yes, yes, yes!!! However, the fact that array names evaluate to the address of the first element in the array means that the types "pointer to foo" and "pointer to array of foo" *must* indicate the same storage layout in C, and this glitch is so deeply ingrained in C that to "fix" it would simply yield a new language, not a better C language. Note that this glitch, coupled with the definition of subscripting in terms of pointer arithmetic, makes the type "pointer to foo" an unresistably convenient near-synonym for "pointer to unknown sized array of foo", and thus nearly everybody uses the simpler form. -- Just because you wind up naked doesn't make you an emperor. --- Padlipsky -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw