Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site brl-tgr.ARPA Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!think!harvard!seismo!brl-tgr!tgr!root%bostonu.csnet@csnet-relay.arpa From: root%bostonu.csnet@csnet-relay.arpa (BostonU SysMgr) Newsgroups: net.unix-wizards Subject: Re: Re: PCC, lint bug Message-ID: <1152@brl-tgr.ARPA> Date: Sun, 1-Sep-85 16:23:51 EDT Article-I.D.: brl-tgr.1152 Posted: Sun Sep 1 16:23:51 1985 Date-Received: Tue, 3-Sep-85 01:29:51 EDT Sender: news@brl-tgr.ARPA Lines: 91 >This really belonged in net.lang.c, for reasons which will be apparent >shortly... > >> The following totally reasonable looking garbage compiles and passes >> lint -hp without a peep. It printed garbage on my 4.2 VAX, core dumped >> on my UNIX/PC (SYSV). I realize the difference between a two dimensional >> array and a pointer to a pointer (or whatever, pluralize), apparently >> neither C nor lint does. Sorry if this has been covered. > (excerpted) > ---------- >> int x[2][2] ; >> int **xp = x ; >> printf("%d\n",x[i][j] = i+j) ; >> printf("%d\n",xp[i][j]) ; > >C does know the difference between "array of X" and "pointer to X"; however, >when the name of an "array of X" is used it evaluates to a pointer to the >first member of that array, hence a "pointer to X". > >xp[i][j] is (xp[i])[j]. xp[i] is *(xp + i). "xp" is a pointer to a pointer >to an "int", as is xp + i. *(xp + i) is thus a pointer to an "int". >(xp[i])[j] is thus (*(xp + i))[j]. Call *(xp + i) Xp. (xp[i])[j] is Xp[j]. >This is *(Xp + j). "Xp" is a pointer to an int, as is Xp + j, so *(Xp + j) >is an "int". The code is perfectly legal C. Any C compiler or "lint" which >*rejected* it would have a bug. Why the program drops core is left as an >exercise for the reader. (Hint - has what "xp" points to been initialized? >Is code that dereferences an uninitialized pointer likely to work?) > > Guy Harris WRONG WRONG WRONG THE ERROR IS ALLOWING THE DECLARATION TO PASS BOTH C AND LINT: int x[STUFF][THING] ; /* the name 'x' is a pointer to an int */ int **xp = x ; /* not a pointer to a pointer */ I do not believe *any* reading of 'x' lets it be a pointer to a pointer. My, ahem, point stands, it's a bug in the compiler not a misunderstanding of C. The semantics of a two dimensional array (x[STUFF][THING]) is not at all the same as an array of pointers (*x[STUFF]), the former involves only a base pointer and STUFF*THING ints (in this case.) Therefore, perhaps, UNIX-WIZARDS, not net.lang.c if I read intentions right (this is where interesting global bugs go.) Here is the code for a trivial proof of this on a VAX (4.2): int x[4][3] ; /* make these externs so the names show up in the asm */ int **xp = x ; /* wrong, type clash, but C nor LINT care */ int i ; foo() { i = 4 ; x[2][2] = i ; xp[2][2] = i ; } (Now, cc -S:) LL0: .data .comm _x,48 <- 4*3*sizeof(int) .align 2 .globl _xp _xp: .long _x <- wrong, type clash .comm _i,4 .text .align 1 .globl _foo _foo: .word L15 jbr L17 L18: movl $4,_i movl _i,_x+32 <- doesn't deref anything, correct (x[2][2]) movl _xp,r0 <- merrily derefs a pointer (xp[2][2]) this is correct code, but the decl should have caused warnings movl 8(r0),r0 movl _i,8(r0) ret .set L15,0x0 L17: jbr L18 .data If you are still not convinced this is a bug, change all the occurrances of 'int' to 'char' above and run it through C and lint, lint only warns when -hp (possible pointer alignment problem ?!?! still wrong.) -Barry Shein, Boston University