multi-d arrays and types

Chris Torek chris at mimsy.umd.edu
Tue Mar 27 05:58:47 AEST 1990


In article <1990Mar26.155319.23986 at ccu.umanitoba.ca>
rpjday at ccu.umanitoba.ca writes:
>  int calendar[12][31];
>  int (*monthptr)[31];
>Clearly, calendar is a 2-d array in the sense that ANYTHING 
>in C is a 2-d array, since all arrays in C are technically
>1-dimensional.  Based on my understanding of arrays in C,
>what calendar is is a 1-d array, whose elements themselves
>are arrays of length 31 of integers.  Right so far?  OK.

Right.

>The variable "monthptr" is now declared as a pointer to 
>an array of length 31 of int, which SHOULD match with
>the type of element of the array calendar, no?

An element of `calendar' has type (int [31]); `monthptr' has
type `(int (*)[31])', so: no.

>Based on this, I write a loop to scan the elements of calendar,
>the outermost loop looking like
>  for (monthptr = calendar; monthptr <= calendar[11]; monthptr++)

The rule is:

    In a value context, an object of type `array N of T' (for any
    constant N and any suitable type T) turns into a value of type
    `pointer to T', whose value is the address of the first (0'th)
    element of the array.

The first part is OK:

	monthptr = calendar;
  =>	<object, ptr to array 31 of int, monthptr> =
		<object, array 12 of array 31 of int, calendar>;

Now apply the rule: N=12, T=`array 31 of int':

  =>	<object, ptr to array 31 of int, monthptr> =
		<value, ptr to array 31 of int, &calendar[0]>;

>My assumption is that the first assignment should not be a
>problem, as we have a pointer being assigned the name of an array
>whose elements have EXACTLY the same type as the pointer.
>This, in fact, works.  "monthptr++" also works as address
>arithmetic increments monthptr by the length of an int[31].

Yes.

>The weirdness is in the comparison which, while it works,
>complains that the types are incompatible ("warning: illegal
>pointer combination").

Because they are:

	monthptr <= calendar[11]
  =>	<object, ptr to array 31 of int, monthptr> <compare>
		<object, array 31 of int, calendar[11]>

(I have skipped a few steps here but the idea should be clear.)  N=31,
T=`int':

  =>	<object, ptr to array 31 of int, monthptr> <compare>
		<value, ptr to int, &calendar[11][0]>

>Putting an "&" in front of "calendar[11]" makes it even worse as the
>compiler complains that I now have "& before array or function", tosses
>the "&", then generates the first warning.

This simply means you have an old (`Classic C') compiler rather than an
ANSI (`New C') compiler.

>The question is, just what the heck type is "calendar[11]"????

It *is* type `array 31 of int'; it *becomes* `pointer to int' because it
is used where a value is needed.

>It seems to me that what I am seeing is some sort of schizophrenic
>behaviour.

This is the reason (or one of the reasons) that ANSI C allows the `&'.

The solution to the whole problem is to replace

	monthptr <= &calendar[11]	/* correct in ANSI C only */

with

	monthptr <= calendar + 11	/* correct in ANSI & old C */

which has the same effect but does not invoke the unnecessary restriction
on `&' in old C compilers.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list