rpjday@ccu.umanitoba.ca (03/26/90)
Consider the following snippet of program, involving
a 2-d array for a calendar.
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.
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? 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++)
{
.....
}
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].
The weirdness is in the comparison which, while it works,
complains that the types are incompatible ("warning: illegal
pointer combination"). 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. The question is, just what the heck type
is "calendar[11]"????
It seems to me that what I am seeing is some sort of schizophrenic
behaviour. "calendar[11]", on the one hand, is an element of
an array, so I should be allowed to apply "&" to it.
On the other hand, it is itself an array so I shouldn't need
the "&" in front of an array. Making things explicit and
using "(int (*) [31]) calendar[11]" finally makes the compiler
stop complaining, but this doesn't get me any closer to figuring
just what type this is, if it isn't already an "int (*) [31]".
Comments?
karl@haddock.ima.isc.com (Karl Heuer) (03/27/90)
In article <1990Mar26.155319.23986@ccu.umanitoba.ca> rpjday@ccu.umanitoba.ca writes: > int calendar[12][31]; > int (*monthptr)[31]; > for (monthptr = calendar; monthptr <= calendar[11]; monthptr++) ... >[Assignment and increment are okay, but the comparison has a problem.] Since "calendar" has type "array of array of int", "calendar[11]" has type "array of int", which decays into "pointer to int", which does not match the "pointer to array of int" on the left side. What you really want is "&calendar[11]", but... >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. Unfortunately, in pre-ANSI C it was not legal to explicitly take the address of an array. (This was a botch; the relationship between arrays and pointers was not as well defined in the old days.) Your options include: [0] use an ANSI C compiler; [1] patch your compiler to remove (nothing to add!) the line that makes this illegal; [2] rewrite your code with a dummy struct around the array; [3] (recommended) change the expression from "&calendar[11]" to "calendar+11", which is equivalent (due to the definition of "[]") but works right even in pre-ANSI C. Oh, I also recommend that you use 12 rather than 11 as the limiting subscript, and change the relational operator to a strict "<". Karl W. Z. Heuer (karl@ima.ima.isc.com or harvard!ima!karl), The Walking Lint
chris@mimsy.umd.edu (Chris Torek) (03/27/90)
In article <1990Mar26.155319.23986@ccu.umanitoba.ca> rpjday@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@cs.umd.edu Path: uunet!mimsy!chris
ark@alice.UUCP (Andrew Koenig) (03/27/90)
In article <1990Mar26.155319.23986@ccu.umanitoba.ca>, rpjday@ccu.umanitoba.ca writes: > Consider the following snippet of program, involving > a 2-d array for a calendar. > int calendar[12][31]; > int (*monthptr)[31]; This example looks a lot like the one that starts on page 30 of `C Traps and Pitfalls,' so let me quote the comment that ends the discussion of that example: At this point we have walked far enough out on the ice that we had better turn back before falling through; although this last example is valid ANSI C, I had trouble finding a compiler that would accept it. If you don't have an ANSI compiler, and a pretty good one, you're likely to be out of luck. -- --Andrew Koenig ark@europa.att.com