allocating arrays
Wayne Throop
throopw at dg_rtp.UUCP
Sun May 11 04:43:47 AEST 1986
Ever alert to save the world from mistaken C code examples that could
have been caught by simple use of lint or other commonly available
tools, our eagle eyed hero finds a particularly silly example. Let's
listen in....
> allbery at ncoast.UUCP (Brandon Allbery)
> | Consider an array of 15 pointers to arrays of doubles:
> | double (*parray[15])[];
> | The following code to 'malloc' the actual double array barfs on Microsoft 'C',
> | with a 'different levels of indirection' warning on the '='.
> | The code passes through LINT, and compiles OK on UN*X 5.2
> | char *malloc();
> | parray[0] = (double*)malloc((unsigned)sizeof(double)*75);
> double (*parray[15])[]; means:
> an indefinitely-sized array of (or a pointer to)
> an array of 15
> (double *)
Wrong. It means just what the original poster said it meant. It is an
array of 15 pointers to arrays of double. What the original poster is
mistaken about is that lint doesn't complain about the example. In
particular, given this example
void f(){
double (*a[15])[];
char *malloc();
a[0] = (double *)malloc((unsigned)sizeof(double)*75);
}
lint (on our system at least) says
warning: illegal pointer combination
(4)
I grant you, this isn't very informative, but lint *doesn't* like it,
that much is certain. Let's run a more blabbermouth tool over it.
#1052 4 inconsistent types discovered
(=
(:AREF
(:IDENTIFIER a :AUTO ... )
(:OCT_INT 0))
(:CAST
(:POINTER_TO
(:DOUBLE))
(:FUNCALL
(:IDENTIFIER malloc :EXTERN ... )
(*
(:CAST
(:UNSIGNED)
(:SIZEOF
... ))
(:DEC_INT 75)))))
Types are:
(:POINTER_TO
(:ARRAY_OF
(:DOUBLE)
() ()))
and:
(:POINTER_TO
(:DOUBLE))
As you can see, this is an attempt to assign a pointer-to-double to a
pointer-to-array-of-double. In this case, it is easy to tell that this
is what is going on even without blabbermouth typecheckers. The
declaration of a is of the form (*[])[], making the type of a[0] (*)[],
a pointer to an array. The cast of the return value of malloc was
simply *, that is, a simple pointer. If you want your compiler to shut
up, you should make the cast read (double (*)[]). When the cast is
changed in this way, lint no longer complains. Changing the cast to
(double **) naturally still causes complaint.
The problem as I see it is that the C compiler led the original poster
astray with a misleading error message. The problem isn't with a wrong
level of indirection, but with an assignment of a value of type
pointer-to-scalar to an lvalue of type pointer-to-array. The compiler
in question seems to have the common misconception that
pointers == arrays in C... they do not.
Now, with all that said, I suspect that what was really wanted was this:
void f(){
double *a[15];
char *malloc();
a[0] = (double *)malloc((unsigned)sizeof(double)*75);
}
This is type-correct, and is probably what is wanted. We have here an
array of 15 pointers to (implicitly, variable sized arrays of) double.
To reference the second double in the implicit array pointed to by the
third pointer in a, one would say a[2][1]. To say the same thing with
the original definitions would be (*a[2])[1].
> My compiler (pcc) won't even TAKE ``double (*parray[15])[];'' unless it's
> initialized or external; apparently sys5 converts it to the declaration
> ``double *(*parray[15]);'' -- ptr to array[15] of (double *) -- automatically.
Yes, the pcc seems to be another beastie with odd (and in some cases
incorrect) ideas about pointers and arrays. Sigh.
--
Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
More information about the Comp.lang.c
mailing list