Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!mcnc!rti-sel!dg_rtp!throopw From: throopw@dg_rtp.UUCP (Wayne Throop) Newsgroups: net.lang.c,net.micro.pc,net.unix Subject: Re: C'mon, guys! Message-ID: <371@dg_rtp.UUCP> Date: Thu, 29-May-86 18:04:46 EDT Article-I.D.: dg_rtp.371 Posted: Thu May 29 18:04:46 1986 Date-Received: Sat, 31-May-86 06:59:46 EDT References: <200@pyuxv.UUCP> <1181@ncoast.UUCP> <350@dg_rtp.UUCP> <3423@ukma.UUCP> <357@dg_rtp.UUCP> <1194@ncoast.UUCP> Lines: 133 Xref: watmath net.lang.c:9227 net.micro.pc:8466 net.unix:8002 Summary: AAAAUUUUGGGGHHHH!!!! > allbery@ncoast.UUCP (Brandon Allbery) > I concede. But it wasn't pointer-vs.-array that threw me; f[] and *f are > identical, whereas f[5] and *f are NOT and neither are f[] = {3} and *f. > What threw me was getting my insides and outsides confused. C declarations > are giving me gray hairs! Anyone for Modula-2? I'm for Modula-2 too. But you don't concede enough, apparently, since you still think that f[] and *f are the same thing, which they are not, and you go on to say: > The declaration is correct, the cast should be to (double **), and MSC is as > screwed up as everything else I've ever seen from Microsoft. (So what's > new?) I'm interested in knowing why your sys5 passed it without an illegal > pointer combo message, though. Which is WRONG, WRONG, WRONG. The cast should be (double (*)[]). Many folks still seem to think that declaring arrays of unknown size is the same as declaring a pointer. It is NOT so. Apparently, I have not convinced you yet. Let's see what various tools say about this example: 1 char *malloc(); 2 void f(){ 3 int (*a)[], (*b)[], (*c)[]; 4 a = (int **) malloc( (unsigned)sizeof(int)*10 ); 5 b = (int (*)[]) malloc( (unsigned)sizeof(int)*10 ); 6 c = (int *) malloc( (unsigned)sizeof(int)*10 ); 7 } Well, what ought to happen here? The assignment on line 5 is the only one which has matching types, so everybody ought to complain about the other two. Our compiler doesn't raise a peep for any of the three, but this doesn't surprise me. C compilers most often take a "parts is parts" attitude, and ignore minor type issues if the intent is "clear". Our local typechecker says (compressing some whitespace): 4 inconsistent types discovered Types are: (:POINTER_TO (:ARRAY_OF (:INT) () ())) and: (:POINTER_TO (:POINTER_TO (:INT))) 6 inconsistent types discovered Types are: (:POINTER_TO (:ARRAY_OF (:INT) () ())) and: (:POINTER_TO (:INT)) Lint, on the other hand, only complains about the assignment on line 6, saying warning: illegal pointer combination (6) So, much to my disgust, lint doesn't catch what I claim is a blatant error. So who're ya gonna believe, me or a stupid program? :-) Let's see if we can't induce lint to see a difference between a pointer and an array with unknown bounds. Let's consider *this* example: 1 #include "stdio.h" 2 void f(){ 3 int (*a)[], **b; 4 printf( "%d %d\n", 5 sizeof *a, 6 sizeof *b ); 7 } This time, our compiler says Error 276 severity 3 beginning on line 5 You cannot take the size of an array with unknown bounds. Our local typechecker doesn't raise a peep (it doesn't attempt to evaluate sizeofs). And lint, glory be, says (5) warning: sizeof returns value less than or equal to zero So, lint *does* know the difference between an array of unknown bounds and a pointer (it correctly complained about applying sizeof to the array, and allowed the sizeof of the pointer), it just doesn't complain if you try to assign a pointer-to-a-pointer to a pointer-to-an-array. That is, lint has a bug, which answers the question as to why lint doesn't call "illegal pointer combo" on line 4 of the first example. Further supporting the contention that lint has a bug, it doesn't complain about this example, which *everyone* should agree is incorrect: char *malloc(); void f(){ int (*a)[10]; a = (int **) malloc( (unsigned) sizeof(int)*10 ); } In this case, lint apparently thinks that (int (*)[10]) is the same type as (int **), clearly wrong. Let's look at one more example. #include "stdio.h" void main(){ int ia[10] = {1}, (*a)[] = (int (*)[])ia; int i = 2, pi = &i, **b = π printf( "%x %x %d %x %x %d\n", a, *a, **a, b, *b, **b ); } This program, when run, prints 70000a18 70000a18 1 70000a14 70000a12 2 So, a shows the contents of the pointer a, *a is an array name, and hence shows the address of the first element pointed to by a, and **a is an integer, the first one in the array *a. On the other hand b shows the contents of the pointer b, *b is a pointer, and hence shows the contents of a second pointer, and **b is an integer, the one pointed to by *b. This shows that (*a)[] is talking about two chunks of storage, one being a pointer to the other, and the other being an array of integers (of unknown size). **b, on the other hand, is talking about *three* chunks of storage, one being a pointer to the second, the second being a pointer to the third, the third being an integer (or, implicitly, an array of integers of unknown size). Note that in both of these cases, only the *first* of the chunks of storage being talked about is allocated by the definition of a or b. Now, have I convinced you all that (*)[] is not the same thing as **, or must I get out......... THE RACK! HA HA HAAAAAA!!! -- "I didn't expect the bloody Spainish Inquisition." --- Monty Python -- Wayne Throop !mcnc!rti-sel!dg_rtp!throopw