Why does C hate 2d arrays?

Daniel E. Platt platt at ndla.UUCP
Sat May 26 01:54:43 AEST 1990


In article <16703 at haddock.ima.isc.com>, karl at haddock.ima.isc.com (Karl Heuer) writes:
> In article <3034 at goanna.cs.rmit.oz.au> ok at goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:
> >There is, however, a silver lining in that cloud.  All you have to do is to
> >write your own array allocator which returns a pointer to a single block of
> >(Nrows pointers then alignment padding then Nrows*Ncols data).
> 
> Yes, ideally one should be able to write
> 	foo_t **p = (foo_t **)alloc2(nrows, ncols * sizeof(foo_t));
> 	p[i][j] = f;
> for arbitrary type foo_t.  Unfortunately, it is impossible to portably write a
> single function, since it has no way to know the type of pointer to use for
> the dope vectors.  (This is why I dropped the function from my private
> library.)
> 

I'm not sure I understand the problem...

How about:

	void **alloc2(nrows, ncols)
	int nrows, ncols;   /* ncols includes size info */
	{
		int i;

		void **tmp;

		if((tmp = (void **)malloc(nrows * sizeof(void *))) == NULL){
			/* do something about this problem */
		}

		for(i = 0; i < nrows; i++)
			if((tmp[i] = (void *)malloc(ncols)) == NULL){
				/* do something about this problem.. need to de-allocate what
				was allocated */
		}
		return tmp;
	}

If you're not using ANSI-C, then you can replace all the 'void's with
'char's and it will work just fine with appropriate type-casting.  My
documentation on malloc indicates that "malloc returns a pointer to a block
of at least 'size' bytes suitably aligned for any use",  which implies that
all you'd need to do in a structure containing doubles is make sure that there
were nice allignment paddings in the structures....

I'm not sure what's wrong with the above approach.  I've written lots of nice
library functions for my use (things like fft's, matrix inversion and
diagonalization, &c) around things like this, and I've had no complaints.
Further, these routines can be used to handle arrays with weird shapes...
Most of the semantics (what a, a[] and a[][] mean) is pretty much the same
at the code level anyway -- it does mean something different at the assembler
level, and the declarations look different -- when comparing doubly dimensioned
arrays with pointer arrays of pointers to arrays.

Or did I miss the point?

> It's impossible for a user to write it in portable C.  

Is the above not portable?

>                                                        But it's relatively
> easy for the *implementor* to provide it, since he can add compiler hooks as
> necessary.  On a vaxlike architecture this would simply be implemented as
> 	#define malloc2d(nr, nc, T) ((T **)alloc2((nr), (nc)*sizeof(T)))
> where alloc2() is the function mentioned earlier.  On a word-addressed
> architecture with two or more flavors of pointers, you use
> 	#define malloc2d(nr, nc, T) ((T **)_alloc2((nr), (nc)*sizeof(T), \
> 		__whichpointer(T)))
> where __whichpointer() is some mapping from types to small integers to encode
> the information about pointers.  (alignof() might suffice.)  Then the actual
> function simply does
> 	switch (wp) {
> 	case __whichpointer(char):
> 	    ((char **)vec)[i] = (char *)&block[i*nc*sz];  break;
> 	case __whichpointer(int):
> 	    ((int **)vec)[i] = (int *)&block[i*nc*sz];  break;
> 	}
> 

I thought malloc() was supposed to handle allignment problems by starting
blocks on the largest appropriate boundary.

Dan Platt

PS... I'm not trying to be argumentative or contrary -- its just that if I've
missed a fine point of C, I'd like to know about it...



More information about the Comp.lang.c mailing list