My pointer stuff: C caught me again (?) but it has truths in it
Brandon Allbery
allbery at ncoast.UUCP
Sat Jun 28 09:33:00 AEST 1986
Expires:
Quoted from <418 at dg_rtp.UUCP> ["Re: Pointers vs. arrays: another dumb question..."], by throopw at dg_rtp.UUCP (Wayne Throop)...
+---------------
| > 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.
+---------------
Believe me, I'm aware of it. Anyone have a PD Modula 2 compiler for a 68000?
+---------------
| 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?
+---------------
I may have messed up, but C's damnable pointer/array stuff has me so confused
I don't know for sure. The basic idea as I understand it is the C array
versus an malloc'ed one.
The code in question is two analogous sections:
-------- section 1 ---------
struct sfld (*__cursf)[] = (struct sfld (*)[]) 0;
if ((__cursf = (struct sfld (*)[]) calloc(n, sizeof (struct sfld)))
== (struct sfld (*)[]) 0) ...
----------------------------
This was intended to allocate an array and assign it to a variable of type
``pointer to array of (struct sfld). I suspect the type is wrong but I'm not
sure how to decalre such a beastie; I suspect that it *does* *not* *exist*
*at* *all* in C, now that I've played with it.
The other section looks like this:
-------- section 2 ---------
struct menu {
int m_rec;
struct cmd *m_cmd;
};
struct menu cmdtab[] = {
orders, ocmdarr,
customer, ccmdarr,
-1, (struct cmd *) 0,
};
----------------------------
The dichotomy between these otherwise identical sections (as far as the
``pointer to an array'' is concerned) is that an array DECLARED in C causes
the array name to become a CONSTANT. Whereas the malloc()'ed one is a POINTER
VARIABLE. This could easily have been done correctly:
int array[3]; -- should declare a pointer followed by 3 integers, with the
pointer initialized to the 3 integers
int array[]; -- should decalre a pointer.
The ``pointers'' I am talking about here are the assembly-language constructs;
C should treat ``int array[]'' as a different type from ``int *ptr'', and
while ``int array[3]'' and ``int array[]'' are the same type, the sized
array's pointer should be treated as a constant. (This may be arguable.)
BTW, the (struct foo (*)[]) was confusion on my part; it's just plain wrong
for what I was doing.
I have become thoroughly sick of C pointers-vs.-arrays. Anyone with a
replacement? If this continues I may go back to programming in BASIC (yes,
it's THAT bad!).
+---------------
| Anyhow, the insightful stuff follows:
|
| > BUT: the arrangement in memory is identical!
+---------------
Not for that cast it wasn't. The actual problem comes from C's closeness to
the machine hardware:
the malloc()'ed one is type (int *), to the C compiler (to me, int [])
the declared one is type (int []), to the C compiler
(which defines (int []) as (int *))
--btw, what REALLY threw me was the idea of a cast to (int []) --
huh? I wholeheartedly agree with your flame re: declaration-
mirrors-use; that cast is ridiculous! ((int (*)[]) is worse!)
and they are in fact identical in memory, so the C compiler treats them as
identical period. Boo hiss; just because on my computer a (long) is the same
size as an (int) doesn't mean I can mix them with impunity. C (and, more
importantly, lint) deals with (long)->(int)->(short), but NOWHERE is there a
utility to catch misuse of * and [].
+---------------
| "Why isn't the correct type of an int array name (int [])?"
|
| *GOOD* question. *VERY* good question. The answer is "just because".
+---------------
AMEN, HALLELUJAH!!!
+---------------
| 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.)
+---------------
This one feature is the only one that has me posting confusing (and wrong)
ideas about C on the net. Abolish it. If I had lint source I would change it
to force arrays to be (int []) and pointers (int *); of course, malloc() would
have to be ``known'' for this to work, so the size allocated could be checked
and the correct type assigned. (malloc(sizeof int) shouldn't have to be cast
to (int []), since it's valid for ``int *foo''.) Meaning, not possible. C
loses again. (HELP!)
+---------------
| > 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.
+---------------
I'm in the process of rewriting programs to use [] where [] is meant and *
where * is meant.
Come to think of it -- can malloc() or similar be typed right anyway? I
suspect this is why Pascal uses the ``new(pointer)'' construct, known to the
compiler; it's type-able at compile time. But catching the allocation of an
(int []) (vs. an (int)) from malloc() and forcing the former to be assigned to
a variable of type (int []) and the latter to an (int *) is nearly
impossible even when the language considers (int []) and (int *) to be
different.
Chuck it out & start over, please!
--Brandon (confusion (*)[])
--
ihnp4!sun!cwruecmp!ncoast!allbery ncoast!allbery at 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)
More information about the Comp.lang.c
mailing list