Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!philabs!mcnc!rti-sel!dg_rtp!throopw From: throopw@dg_rtp.UUCP (Wayne Throop) Newsgroups: net.lang.c,net.micro.pc,net.unix Subject: Re: allocating arrays Message-ID: <350@dg_rtp.UUCP> Date: Sat, 10-May-86 14:43:47 EDT Article-I.D.: dg_rtp.350 Posted: Sat May 10 14:43:47 1986 Date-Received: Mon, 12-May-86 00:18:48 EDT References: <200@pyuxv.UUCP> <1181@ncoast.UUCP> Lines: 101 Xref: linus net.lang.c:8226 net.micro.pc:7785 net.unix:7163 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@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 !mcnc!rti-sel!dg_rtp!throopw