Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site ucbvax.ARPA Path: utzoo!watmath!clyde!burl!ulysses!ucbvax!anton From: anton@ucbvax.ARPA (Jeff Anton) Newsgroups: net.unix-wizards Subject: Re: Re: PCC, lint bug Message-ID: <10287@ucbvax.ARPA> Date: Fri, 6-Sep-85 17:02:07 EDT Article-I.D.: ucbvax.10287 Posted: Fri Sep 6 17:02:07 1985 Date-Received: Sat, 7-Sep-85 06:44:29 EDT References: <1152@brl-tgr.ARPA> <81@copper.UUCP> Reply-To: anton@ucbvax.UUCP (Jeff Anton) Followup-To: net.lang.c Organization: University of California at Berkeley Lines: 120 Those who have had enough of the junk should only read this first page. >>>> int x[2][2] ; >>>> int **xp = x ; >>>> printf("%d\n",x[i][j] = i+j) ; >>>> printf("%d\n",xp[i][j]) ; int **xp = x; /* is wrong, wrong, wrong; lint should not accept this */ int xp[][2] = x; /* is right */ int (*xp)[2] = x; /* is also right */ int *xp[2] = x; /* is WRONG */ I'm disgusted at the number of 'wizards' who are confused. 'x' should best be though of as a pointer to array of two ints. int y[2][2][2]; /* y should best be thought of as a pointer to two dimentional array of ints ([2][2]) */ int yp[][2][2] = y; /* is a proper pointer */ In article <81@copper.UUCP> scottha@copper.UUCP (Scott Hankerson) writes: >In article <1152@brl-tgr.ARPA> root%bostonu.csnet@csnet-relay.arpa (BostonU SysMgr) writes: >> >>>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, ---> This writer doesn't. (JAA) >>>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 ---> No cigar for Guy, He's got the semantics of 'xp' down, but not 'x'. >> >>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. >> -Barry Shein, Boston University ---> Barry understands the problem but not the solution. > >Who is WRONG WRONG WRONG?? Page 104 of the 1978 edition of \The C >Programming Language/ by Kernighan and Ritchie says: > > In C, by definition a two-dimensional array is really a > one-dimensional array, each of whose elements is an array. ---> K & R are right. int (*xp)[2]; /* xp is a pointer to array of 2 ints */ ---> Thus, xp++ moves xp past two (2) ints > Hence subscripts are written as > > day_tab[i][j] > > rather than > > day_tab[i, j] > > as in most languages. Other than this, a two-dimensional array > can be treated in much the same way as in other languages. > >There's still the question of whether or not xp (in the original example) >is properly initialized. But since when did C care if a pointer is >initialized? > >Scott Hankerson >tektronix!copper!scottha I thank those people who understand this stuff and are still reading. C does have a problem here. Consider the case where you wish to pass multi-dimentional arrays to utility functions. Currently, the receiving function must be compiled with proper dimentions. ex: foo(matrix) /* proper definition for passing 4x4 arrays */ double matrix[][4]; { .... C should let you pass what dimentions you want. ex: bar(matrix, dim) double matrix[][dim]; { .... This does add complexity, but the only way around the problem now is to do your own array deref: baz(matrix, dim) double matrix[]; /* note one dimention */ int dim; { double d = matrix[2*dim+3]; /* to get matrix[2][3] */ Of course, you can avoid the whole mess by working by useing an array of pointers to array of type. ex: int *x[2]; int x0[2], x1[2]; /* later */ x[0]=x0; x[1]=x1; But this requires run time code to set up properly. (I think I've managed to send follow ups to net.lang.c automagically for those people who are impulsive with 'f'.) -- C knows no bounds. Jeff Anton U.C.Berkeley Ingres Group ucbvax!anton anton@BERKELEY.EDU