Passing Multidimensional Arrays

Joseph S. D. Yao jsdy at hadron.UUCP
Wed Dec 18 17:56:14 AEST 1985


Several pretty good responses to this have already come across
(where can I get the lint with that fabulous output??), but they
managed to miss a fairly important point.

In article <365 at codas.UUCP> mikel at codas.UUCP (Mikel Manitius) writes:
>[MISSING ATTRIBUTION]
>> I have an application where I want to pass a 2D array to a subroutine.
>How about this:
>#define		X	100
>#define		Y	100
>struct	x a[Y][X];
>subrout(i, j, a)
>int	i;
>int	j;
>struct x *a[];
>{
>	...a[j][i]...
>}
>And use i and j as boundary limits.

The major thing wrong with this is that, in this case, pointers
and arrays are  n o t  the same thing!  The declaration a[Y][X]
declares a series of data objects:
	a[0][0], a[0][1], ... , a[0][X], a[1][0], a[1][1], ... a[Y][X]
WHEREAS the declaration *a[] declares a series of pointers to
data objects!  as:
	ptr(a[0][0]), ptr(a[1][0]), ...
This latter object DOES NOT EXIST.  Using the above declaration,
trying to find a[0][0] results in the following sequence of
operations:
	first find a[0].  Oh, since a is an array of pointers,
	the first element is the pointer a[0].  (But in the outside
	world, this is the data object a[0][0].)

	now find (a[0])[0].  but a[0] was a pointer.  therefore,
	find whatever that pointer was pointing to.  (Which, to
	the outside world means that you are indirecting off the
	data object a[0][0] ... which was a structure ... I'm
	sure you are getting sick now thinking of what this must
	be doing ...)

Of course, the only reason I know this so thoroughly is that early
in my UNIX career, about a dozen years ago, I did exactly this and
blew a machine totally away.

The correct declaration is either a[Y][X] or even a[][X].  An
array may be declared with the first size left blank or arbitrary,
but all the rest must be filled in.

For those of you who aren't tired of this yet, here's a picture
of the two different structures in memory:

a[Y][X]:
	a:  _  _  _  _  _  _  ...  _  _  _  _  _  _
	    _  _  _  _  _  _  ...  _  _  _  _  _  _
	    ...
	    _  _  _  _  _  _  ...  _  _  _  _  _  _
	a+(X*Y*sizeof(a[0][0]):

versus *a[]:
	a:  _ -> b
	    _ -> c
	    ...
	    _ -> omega
	a+(Y*sizeof(ptr to a)):
	...
	b:  _  _  _  _  _  _  ...  _  _  _  _  _  _
	b+(X*sizeof(a[0][0]):
	...
	c:  _  _  _  _  _  _  ...  _  _  _  _  _  _
	c+(X*sizeof(a[0][0]):
	...

Note that **argv and *argv[] may be used identically, but that
argv[][] has never been used and is incorrect, e.g. .  The reasons
are left to the student as an exercise.		;-)
[If you take that seriously, post answers to me,  n o t  the net!]
-- 

	Joe Yao		hadron!jsdy at seismo.{CSS.GOV,ARPA,UUCP}



More information about the Comp.lang.c mailing list