[net.sources] Dynamically Allocate Your Multi-Dimensional Arrays

jeff@gatech.CSNET (Jeff Lee) (04/22/85)

Several people over the past several months have asked about how to
allocate pointer structures that looked like multi-dimensional arrays
to C (technically, these would be considered dope-vectors). This seemed
like an interesting exercise and I was also interested in the possible
speed-up obtainable by indirection over multiplication. Anyway, to
make a short story long, the procedure 'dope' should allocate a multi-
dimensional array dynamically for you and it should be relatively
portable. I have tested it as well as I can given that I really don't
have any applications for it. I put the numbers in the different locations
and they come out later. If it has problems send them to me and I'll see
what I can do. Send me nice mail and I'll be nice and try to help. Send
me nasty mail and I'll tell you that if you don't like it, don't use it.

As for portability, I assume that (char *)'s are the same size as pointers
to structures. If you are on a Pr1me or some other strange piece or hardware
where this is not so then you are on your own. Send me the fixes that you
come up with. I also assume that a structure is padded to the correct
boundaries on both ends, ie - that if I put two of them immediately side-by
side, the second one is still going to be aligned correctly. Oh, yes...
it also uses varargs.h. I have tested it on a VAX (4.2bsd) and a Pyramid
(OSx 2.3.1) and it seems to work. I may have my head screwed on sideways
looking out my ears, but it seemed to work. Oh well....on to the code.

--------------------------- cut here -------------------------------
/*
*	dope --- allocate a dynamic, dope-vectored array
*
*	calling sequence:
*
*		char *dope(esize, ndim, dim1, dim2, ... , dimn)
*
*	esize --- the size of the element-type to allocate. this should
*		be a 'sizeof' operator in order to ensure it will work.
*	ndim --- the total number of dimensions that the array will contain.
*	dim1-n --- the size of each dimension
*
*	this routine depends on the 'sizeof' operator including all padding
*	to the correct boundary and since 'malloc' ensures that the pointer
*	returned falls on a correct boundary, everything should work out.
*	the one possible problem that I could think of was if character
*	pointers are not the same as other types of pointers (true on some
*	machines). if this is the case, you're on your own. let me know
*	how you fixed this to work in the general case on your machine.
*
*			< dumb copyright notice goes here >
*
*	(c) Copyright 1985 by Jeff Lee and Georgia Institute of Technology
*		(because they own half of my buns, anyway)
*
*	Explicit permission is given to use, distribute, copy, and do strange
*	things with a fork to this software, but you may not sell it because
*	Georgia Tech's name is on it and I believe in free software.
*/

#include <varargs.h>

char *dope(va_alist)
va_dcl
{
	va_list ap;
	int i, j, ldim, fdim;
	int size, bsize, esize, ndim;
	char *array, *next;
	char **index;
	char *malloc();

/*
*	collect and validate the arguments
*/

	va_start(ap);
	esize = va_arg(ap, int);
	ndim = va_arg(ap, int);

	if (ndim <= 0 || esize <= 0)
		return(0);

	for (i = bsize = 0, size = 1; i < ndim; i++)
	{
		if ((size *= va_arg(ap, int)) <= 0)
			return(0);

		bsize += size * ((i == ndim - 1) ? esize : sizeof(char *));
	}
	va_end(ap);

/*
*	allocate the amount of buffer space needed to hold everything
*/

	if ((array = malloc((unsigned) bsize)) == 0)
		return(0);

/*
*	attempt to fill in the pointers in the appropriate places
*/

	va_start(ap);
	(void) va_arg(ap, int);
	(void) va_arg(ap, int);
	ldim = va_arg(ap, int);
	for (i = bsize = 0, size = 1; i < ndim - 1; i++)
	{
		fdim = ldim;
		size *= fdim;
		ldim = va_arg(ap, int);
		index = (char **) (array + bsize);
		bsize += size * sizeof(char *);
		next = array + bsize;

		for (j = 0; j < size; j++)
		{
			*index++ = next;
			next += ldim * ((i == ndim - 2) ? esize :
							sizeof(char *));
		}
	}

	va_end(ap);
	return(array);
}
--------------------------- cut here -------------------------------
Jeff Lee
CSNet:	Jeff @ GATech		ARPA:	Jeff%GATech.CSNet @ CSNet-Relay.ARPA
uucp:	...!{akgua,allegra,hplabs,ihnp4,linus,seismo,ulysses}!gatech!jeff
-- 
Jeff Lee
CSNet:	Jeff @ GATech		ARPA:	Jeff%GATech.CSNet @ CSNet-Relay.ARPA
uucp:	...!{akgua,allegra,hplabs,ihnp4,linus,seismo,ulysses}!gatech!jeff