allbery@ncoast.UUCP (Brandon Allbery) (05/08/86)
Expires: Quoted from <200@pyuxv.UUCP> ["Microsoft 'C' - Strange behaviour with doubles"], by cim2@pyuxv.UUCP (Robert L. Fair)... +--------------- | 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); | | Microsoft produces the same error if the coercion is (double**), (double), | or nothing at all ! | | Any ideas ? +--------------- double (*parray[15])[]; means: an indefinitely-sized array of (or a pointer to) an array of 15 (double *) You want to allocate an array[15] of (double *)? ``double *parray[15];'' ...an array of 15 (double)? ``double parray[15][];'' 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. --Brandon -- decvax!cwruecmp!ncoast!allbery ncoast!allbery@Case.CSNET ncoast!tdi2!brandon (ncoast!tdi2!root for business) 6615 Center St. #A1-105, Mentor, OH 44060-4101 Phone: +01 216 974 9210 CIS 74106,1032 MCI MAIL BALLBERY (part-time) PC UNIX/UNIX PC - which do you like best? See <1129@ncoast.UUCP> in net.unix.
throopw@dg_rtp.UUCP (Wayne Throop) (05/10/86)
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 <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
david@ukma.UUCP (David Herron, NPR Lover) (05/14/86)
[My mailer doesn't know anything about dg_rtp.UUCP, could you please let uucpmap@cbosgd know of your existance????] In article <350@dg_rtp.UUCP> you write: >> 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 I respectively submit that you're full of it and that Brandon is correct. Using []'s in a declaration is SIMILAR to declaring a pointer, 'cept that the pointer is an internal constant in the compiler, and if you fill in a value inside the []'s it allocates some space. A stumbling point is when a [] declaration is an arg to a function, THAT gets translated to a * declaration... Some examples: char a[] = "this is a character string\n"; char b[]; (oh, they're both external decl's) Tell me tho, what USE is a the declaration of b[]???? Translating the decl to *b isn't doing what I SAY, and (on Unix anyway) what I SAY is what I MEAN. Anyway, compiling I get: Undefined: _main _b _main is undefined because I don't have a main() obviously. _b is undefined because it knew that somewhere there's a b[] and made a reference to it. Modifying it to read: char a[] = "this is a character string\n"; main() { char b[], *c; char *malloc(); printf("b = 0x%x\n", b); /* b = */ c = malloc(5); printf("b = 0x%x, c = 0x%x\n", b, c); } produces: b = 0x7fffe880 b = 0x7fffe880, c = 0x2800 (BTW, this is a Vax running 4.2BSD, and we have the "hated" pcc, a value like the one for b is a stack location) Originally I had the b[] decl by itself and the compiler swallowed it. (I have no idea what the compiler thought I wanted to do with a b[]...) But it didn't like it when I had the b = uncommented... (which is what I'd expect). Looking at the assembler output, b[] is a pointer to the top of the stack but there's no space allocated to it. There's only space allocated for the *c. > > 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) Right. the pcc says "illegal lhs" or something to that effect. Which is correct... there's no space allocated to your a. > >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. > ... [deleted, for the sake of brevity, some very interesting output] > >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. er... where did you get that program? I agree with it somewhat EXCEPT it's not making a distinction about CONSTANT pointers a la arrays. It's an interesting program nonetheless... I agree with you that the compilers need to produce better error messages. -- David Herron, cbosgd!ukma!david, david@UKMA.BITNET, david@uky.csnet
throopw@dg_rtp.UUCP (Wayne Throop) (05/22/86)
> david@ukma.UUCP (David Herron) >> throopw@dg_rtp.UUCP (Wayne Throop) >>> allbery@ncoast.UUCP (Brandon Allbery) >>> | ??? > [My mailer doesn't know anything about dg_rtp.UUCP, could you please > let uucpmap@cbosgd know of your existance????] [It has been done, long ago. We are (finally!) on the latest maps. Also, my .signature shows a path to dg_rtp from mcnc, and mcnc is quite well known (being part of the backbone, I beleive).] >>> | Consider an array of 15 pointers to arrays of doubles: >>> | double (*parray[15])[]; >>> 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. > I respectively submit that you're full of it and that Brandon is correct. I exasperatedly submit that I'm quite empty of it, and that Brandon is as wrong as wrong can be. Also, after saying I'm wrong, your examples go on to support my position strongly, so you've succeeded in puzzling me no end, as well as prolonging this discussion beyond it's natrual span. But meanwhile, long ago, in an address space far, far away.... POINTER WARS The Evil Empire has attempted to perpetuate the fallacy that pointers are the same thing as arrays. The brave, outnumbered, noble, correct, long- suffering rebel alliance has always maintained that the Force keeps pointers and arrays distinct. Our hero (moi) has lived a peaceful existance on the out-of-the-way node dg_rtp for years, until finally an empire star destroyer (which insists that stars ("*") in declarations can be replaced by brackets( "[]")) finds dg_rtp via the news network, and opens fire.... Let's listen in, as the battle begins... > [Shhhh-Pfoooo... Shhhh-Pfoooo...] [You can't fool me, Darth Vader! I know that's you behind the life-mask!] > Using []'s in a declaration is SIMILAR to declaring a pointer, 'cept > that the pointer is an internal constant in the compiler, and if you > fill in a value inside the []'s it allocates some space. A stumbling > point is when a [] declaration is an arg to a function, THAT gets > translated to a * declaration... Yeah, right, [] is just like a pointer, except that it isn't, really. Give me a break. A [] declaration always declares an array, and arrays and pointers are *NOT* (I'll repeat for those who have trouble understanding this concept: *NOT*) the same thing. The fact that array formal arguments must "actually" be pointers is no more significant than the fact that character formal arguments must "actually" be integers. And while declaring *anything* is to some degree similar to declaring anything else, pointers and arrays are not really very similar. > Some examples: > > char a[] = "this is a character string\n"; > char b[]; > > (oh, they're both external decl's) Tell me tho, what USE is a > the declaration of b[]???? Translating the decl to *b isn't > doing what I SAY, and (on Unix anyway) what I SAY is what I MEAN. What's the big deal? This says that "a" is an array 28 characters long (unless I've counted wrong... which is the reason for this shorthand in the first place), and storage for "a" is allocated in this file, and initialized to the given string. In addition, you are saying that "b" is an array of unknown size, and storage for it is *not* allocated in this file (that's why it can be of unknown size... the storage will be allocated somewhere else). (What use is "b"? My good sir, what use is a baby?) Given all this, is it hardly surprising that > Anyway, compiling I get: > Undefined: _b since you implicitly promised to allocate space for "b" somewhere else, and then didn't do it. So where's the strangeness? How does all this flapdoodle support your contention that "double (*parray[15])[]" isn't an array of pointers to arrays of double? [ Let me be clear about what "shorthand" I'm talking about above. In C, the declaration char a[] = "ab"; is shorthand for char a[3] = {'a', 'b', '\0'}; (though there is some debate as to whether that "'\0'" should be "0" instead, or exactly what '\0' means (does it mean zero or ascii null?)) This is *NOT* the same as the declaration char *a = "ab"; which isn't shorthand for anything, and which behaves quite differently. The array declaraction allocates storage of size 3, and initializes those three characters to the values given. The pointer declaration allocates storage for one pointer (on our machine, of size 4), and initializes it to point at the first character of a constant array of size 3. As I say, quite different. ] > [another example, simplified: > f(){ > char b[]; > printf( ... b ...); > } ] > Looking at the assembler output, b[] is a pointer > to the top of the stack but there's no space allocated to it. Actually, the declaration of b is illegal, and our compiler complains bitterly about it. I assume your compiler treated it as a zero-sized array. I doubt that it treated it as a pointer, as you suggest. (Interestingly, lint doesn't complain about it. It certainly ought to.) >> [verbose typechecker output, deleted] > er... where did you get that program? I agree with it somewhat EXCEPT > it's not making a distinction about CONSTANT pointers a la arrays. It's > an interesting program nonetheless... Well, the program is a typechecker that was locally written to check the rules as laid out in Harbison and Steele, sort of the new testament to K&R's old. Sadly, I'm not currently at liberty to release it. It is making all the distinctions it should. It was created in essence by going through H&S (as well as K&R), and translating the type rules found there into checks performed against the parse tree of the input C program. Each error message is in fact related back to where H&S justifies calling the construct an error. I trust it a fair amount more than I do lint (though, to my utter dismay, it didn't complain about "f(){char b[];}" either... if anybody can justify why that should be legal (as I say, our compiler complains bitterly), I'd appreciate a message explaining why). > I agree with you that the compilers need to produce better error messages. Good. I hope you now also agree that compilers should keep the differences between pointers and arrays straight. Keep away from the Dark side of the Force, and you can't go wrong. I stress again, the declaration int (*a)[]; is *NOT* (i say) *NOT* (i say again) *NOT* the same as the declaration int **a; and any entity that thinks they *are* the same thing is, quite simply, mistaken. Trust me folks... I'm right about this. If you think these two are the same, you simply haven't thought about it enough. -- "Luke... use the Force!" -- "He's turned his targeting computer off!" -- Stay tuned for the next exciting episode, The Umpire Strikes Out Coming soon to a netnode near you! -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw
throopw@dg_rtp.UUCP (Wayne Throop) (05/23/86)
> david@ukma.UUCP (David Herron) >> throopw@dg_rtp.UUCP (Wayne Throop) Oh yeah, about that example the pcc says "illegal lhs" about... (Don't know how I let this slip by before. Oh well, I can fix it now.) >> 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) > > Right. the pcc says "illegal lhs" or something to that effect. Which > is correct... there's no space allocated to your a. Wrongo. The array "a" is an array of 15 pointers to arrays of double (is anybody getting bored with this?), and thus has 15 pointer-sizes allocated for it, on the stack in this case. Take this program for example: void main(){ double (*a[15])[]; printf( "elements in a = %d\n", sizeof(a) / sizeof( double (*)[] ) ); } Now, let's examine this program with a debugger. Positioning to this module, and asking it to describe "a", we get ARRAY [ 0..14 ] OF POINTER TO ARRAY [ 0..0 ] OF FLOAT BOUND 64 That is, this is an array of pointers to arrays of doubles, just as I've been trying to *tell* you. In particular, there are 15 pointers in this array (that is, the bounds are 0 to 14). But let's see how much space the compiler has allocated for this array on the local stack frame. We position to main, and disassemble the first instruction (the allocation of stack space), and find WSAVR 17 OK. That's 15 (octal 17) 32-bit words of storage allocated to "a". Finally, let's run the blasted thing, and see how many elements *IT* thinks it allocated for "a": elements in a = 15 If the pcc says that the assignment is illegal, that's fine with me since it (sort of) is. But it had better be able to accept a[0] = (double (*)[])malloc((unsigned)sizeof(double)*75); Now *this* assignment is perfectly legal, since a[0] is a pointer to an array of double (that is, (double (*)[])). Fairly conclusive, I'd say. Are y'all convinced? -- "I've seen things you people wouldn't believe. Attack ships on fire off the shoulder of Orion. I watched C-Beams glitter in the dark near the Tanhauser Gate. All those moments will be lost in time, like tears in rain. Time to die." Roy Baty, N6MAA10816, Nexus6, Combat Model -- "I've seen blunders you people wouldn't believe. Pointers confused with arrays as arguments. I watched C-hackers make stupid mistakes on net.lang.c. All of these moments will be lost in time, like a posting on net.philosophy. Time to logout." Wayne Throop, throopw@dg_rtp, Comedy Model -- Wayne Throop <the-known-world>!mcnc!rti-sel!dg_rtp!throopw