My pointer stuff: C caught me again
Chris Torek
chris at umcp-cs.UUCP
Sun Jun 29 13:56:07 AEST 1986
Perhaps I just have an odd mind, but all this pointer/array stuff
never really bothered me.
In article <1267 at ncoast.UUCP> allbery at ncoast.UUCP (Brandon Allbery) writes:
>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.
Why not simply use a `pointer to struct sfld'? If you intend to
use this as `__cursf[i].field', that is what you need.
>The other section looks like this:
>
>struct menu {
> int m_rec;
> struct cmd *m_cmd;
>};
>
>struct menu cmdtab[] = {
> orders, ocmdarr,
> customer, ccmdarr,
> -1, (struct cmd *) 0,
>};
This looks reasonable to me.
>The dichotomy
What dichotomy? Using my declarations everything is identical;
in
/* given `int a[N];' */
a;
the type of the expression `a' is `pointer to int'.
>between these otherwise identical sections (as far as the
>``pointer to an array'' is concerned)
You should to have a two-dimensional array in mind in the first
place before using `pointer to array N'. In
/* int b[M][N]; */
b;
the type of the expression `b' is `pointer to array N of int'.
(Note that if this is dereferenced, it becomes `array N of int',
which in a normal expression is then immediately converted to
`pointer to int'. `normal' here means `not a target of sizeof'.)
>is that an array DECLARED in C causes the array name to become
>a CONSTANT.
Not quite, but close. When used as an rvalue the constant has
type `pointer to' whatever one element of that array might be.
>Whereas the malloc()'ed one is a POINTER VARIABLE.
No, it is a pointer expression, with type `pointer to' whatever
one element of that array might be. Once it has been assigned to
a pointer variable, then that is indeed a pointer variable.
There are certainly other ways of handling the typing of arrays;
C does it by making arrays second class objects, which is occasionally
regrettable, but not too hard to deal with.
>+---------------
>| Anyhow, the insightful stuff follows:
>|
>| > BUT: the arrangement in memory is identical!
>+---------------
The arrangement in memory of any array of any dimension is flat.
`int a[2][5]' is, aside from typing information, identical to
`int a[10]'. This has never bothered me.
>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 [])
Yes.
> the declared one is type (int []), to the C compiler
Yes. Note that the first dimension of the array is unimportant after
allocation, so the type *is* (int []), not (int [5]) or whatnot.
(Again, `sizeof' is peculiar; ignore it.)
> (which defines (int []) as (int *))
Only in `most places' (this is perhaps what bothers people; `sizeof'
is `peculiar', and so are declarations of formals).
>+---------------
>| "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.)
>+---------------
Again, it has never bothered me. Arrays are second class objects;
you cannot quite name one outside a data declaration. Functions
are likewise second class: a function name, when evaluated, does
not yeild a function type, but rather a function pointer. Lunacy?
I guess you should reserve a place in the nut-house for me (though
it is arguable that at UMCP, I am already there :-) ).
Incidentally,
int (*p)[];
is not really a useful declaration. Pretend you are a compiler:
tell me how to find p[3][1] (or, if you prefer, (*(p+3))[1]).
Try again with
int (*p)[5];
and see if that makes a difference.
[answers below]
The rule for pointer addition is `multiply the integer value by
the size (in bytes) of the pointed-to object, then add that to the
address given by the pointer.' Given `int (*p)[]', we want to find
p[3][1]. This is equivalent to *((*(p+3))+1). Do the innermost
expression first: p+3. Following the pointer addition rule, multiply
3 by the size of whatever p points to. p points to `int []'. How
big is this? Got me. It is *not* (sizeof (int *)). See what your
compiler says about `sizeof (int [])'.
For `int (*p)[5]' and the same reference, we take the size of
whatever p points to, and p points to `int [5]'. How big is this?
Well, it depends on your machine, but let us suppose you have a
Vax; we get 5*4 = 20 bytes. We take the address of location (p +
20 bytes), not the contents, as the type of *p is `int []' (the
first subscript drops out of any array type), and since this is
used in another expression, convert the type to `int *'. We now
want to add one to this pointer, so again we follow the pointer
addition rule and take the size of the type of the pointed-to object
(int), which is four bytes, and multiply by 1 (remember, we are
now doing *(<thing> + 1)). <thing> happens to be (p + 20 bytes),
to which we add 4 bytes. The location of p[3][1] is thus (p + 24
bytes), and the type is `int'. If `p' is a register (call it r11),
the expression
i = p[3][1];
should compile to
movl 24(r11),_i
and indeed it does.
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP: seismo!umcp-cs!chris
CSNet: chris at umcp-cs ARPA: chris at mimsy.umd.edu
More information about the Comp.lang.c
mailing list