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