PCC, lint bug

Jeff Anton anton at ucbvax.ARPA
Sat Sep 7 07:02:07 AEST 1985


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 at copper.UUCP> scottha at copper.UUCP (Scott Hankerson) writes:
>In article <1152 at brl-tgr.ARPA> root%bostonu.csnet at 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 at BERKELEY.EDU



More information about the Comp.unix.wizards mailing list