C'mon, guys!
Wayne Throop
throopw at dg_rtp.UUCP
Fri May 30 08:04:46 AEST 1986
> allbery at 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 <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
More information about the Comp.lang.c
mailing list