Path: utzoo!utgpu!news-server.csri.toronto.edu!rutgers!cs.utexas.edu!uunet!jarthur!dfoster From: dfoster@jarthur.Claremont.EDU (Derek R. Foster) Newsgroups: comp.lang.c Subject: Re: Dynamic and Variable Length Structures Message-ID: <5408@jarthur.Claremont.EDU> Date: 25 Mar 90 00:36:07 GMT References: <5624@rouge.usl.edu> Distribution: usa Organization: Harvey Mudd College, Claremont, CA 91711 Lines: 157 In article <5624@rouge.usl.edu> pcb@gator.cacs.usl.edu (Peter C. Bahrs) writes: >I want to write a dynamiclly dimensioned container type (oo flavors) >that is dynamic in the size and number of dimensions, hopefully without >any bounds on either. > >Suppose I want to create a thing that can point to integers. So I want to write > Type? *x; > x = dim(3,4,5); > or > dims[0]=3;dims[1]=4;dims[2]=6;dims[3]=4; dims[4]= -1; > Dim (x, dims); >And now to get an integer I want to say: y = Retrieve(x,dims) where dims >now contains the index (i.e. x[2][3][4] or x[4][8]) > >I CAN put a bound on the dimension and use something like > int ***x; /* 3 dimensions */ > x = (int ***) calloc (N1, sizeof (int **)); > then for each x[i] : x[i] = (int **) calloc (N2, sizeof (int *)); > and x[i][j] = (int *) calloc (N3, sizeof (int)); > so: y = x[a][b][c] is valid; > >Yuck (or is it?) > >Is there any way to parameterize the (int ***) casts into a #define or an >array so that a simple loop index will invoke the appropriate level of cast? >This may imply that x should be of type void *. >Does anyone have any ideas on a solution? There is a fairly elegant (in my opinion) way to do this. It looks somewhat involved. However once the basic routines are written, they need only be called. Take a look at the code I have sketched out below, and consider modifying it to suit your needs. The basic "Idea" is to assume that all pointer types are the same size (and representation) as a void pointer (I know this isn't always portable), and to use a recursive routine to allocate your arrays. The routines below declare variable-sized arrays with variable number of dimensions, of any type. You may be able to simplify them somewhat by restricting the types to integers, etc. The corresponding "FreeArray" functions are "left as an exercise for the reader." Also, for arrays with truly variable numbers of dimensions, you may need to write a Retrieve(x[a][b],c,type) macro. Take a look at my suggestions after the functions, also. I haven't tried to compile these (This is just a sketch - I'm writing off the top of my head), so there may be errors. Note that the dims[] array contains dimensions in the REVERSE order that your post specified. This simplifies the procedures. ----------- #define POINTERSIZE sizeof(void *) /* you never need to call this directly (unless you really want to.) */ /* The next function is a nicer "front end" to it. */ void * AllocDimension(size_t elsize, unsigned Ndim, int dims[]) { void * * c; int i; if (Ndim < 1) return(NULL); if (Ndim == 1) temp = malloc(elsize * dims[1]); else { c = (void * *) malloc(POINTERSIZE * dims[Ndim]); for (i=0; i/*----------- Thanks in advance... --------------------------------------+ >| Peter C. Bahrs | >| The USL-NASA Project | >| Center For Advanced Computer Studies INET: pcb@gator.cacs.usl.edu | >| 2 Rex Street | >| University of Southwestern Louisiana ...!uunet!dalsqnt!gator!pcb | >| Lafayette, LA 70504 | >+-----------------------------------------------------------------------*/ Hope this helps! Derek Riippa Foster