home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!spool.mu.edu!uwm.edu!ogicse!news.u.washington.edu!carson.u.washington.edu!dfitts
- From: dfitts@carson.u.washington.edu (Douglas Fitts)
- Newsgroups: comp.lang.c
- Subject: Re: Accessing a dynamical 3-D field
- Summary: Functions for dynamic allocation with variable bounds
- Message-ID: <1hvm0kINN6l2@shelley.u.washington.edu>
- Date: 31 Dec 92 20:43:00 GMT
- Article-I.D.: shelley.1hvm0kINN6l2
- References: <1992Dec29.142134.25641@Informatik.TU-Muenchen.DE>
- Sender: dfitts@u.washington.edu <Doug Fitts>
- Distribution: world
- Organization: University of Washington, Seattle
- Lines: 186
- NNTP-Posting-Host: carson.u.washington.edu
-
- In article <1992Dec29.142134.25641@Informatik.TU-Muenchen.DE> backscha@Informatik.TU-Muenchen.DE (Martin Backschat) writes:
- >
- >In my program I use 3-D fields of doubles with variable bounds.
- >This field is implemented as an array of doubles which is allocated
- >dynamically with malloc.
- >To access for example the [i][j][k] component in the field f of dimension U,V,W
- >I have to write f[i*V*W + j*W + k].
- >
- >Now my question:
- >
- >Is it somehow possible to declare and allocate a 3-D field u (of doubles) with
- >variable bounds, allocated by malloc, in such a way that it can be accessed
- >with
- >u[i,j,k] (with type casting)?
-
-
- Yes, if u[i][j][k] will do instead of u[i,j,k].
-
- Here are functions similar to ones I use to allocate and free 3-D
- variably-dimensioned arrays in MS C7. I've modified this, so there
- may be bugs, but it runs with the main() here. To be less portable
- and more flexible, use the "_far" keyword and _fmalloc(). As the
- comments say, first declare an appropriate pointer to serve as the base
- of the array, then set it equal to the return value using a cast to the
- type. In your case this would be double, but it could be char, unsigned,
- or long double - whatever.
-
- Access the array as buffer[1][2][0], etc. As with any array in C,
- be very careful not to overrun the length of any of these arrays -
- always access using the same bounds values & arrays you pass to
- this function. Also, always immediately check for a NULL buffer
- on return in case you've run out of memory in the segment
- (or write these as _huge if your compiler supports it).
-
- Always free using the special function free3D(). You have to pass
- the freeing function the address of buffer, not just buffer, because you
- can't set the base pointer to NULL otherwise. Note that the parens
- around (*a) are important. The "if" statements are necessary in case
- the call to free3D() is coming from dim3D() with an incompletely
- populated array. It's not necessary to pass array nfst, because the
- memory manager remembers how many of these there were (in the heap).
-
- E-mail me if you have any trouble. Hope it's what you want.
-
-
-
-
-
-
- #include <malloc.h> /* _fcalloc(), calloc() */
- #include <stdio.h> /* printf(), NULL */
- #include <stdlib.h> /* exit (), for main() only; ANSI calloc() */
-
- /* function prototypes */
- int main( void );
- void ***dim3D( int, int *, int *, size_t );
- void free3D( void ****, int, int * );
-
- void ***dim3D( int slow, int *med, int *fast, size_t bytes )
- {
- /* slow, dimension of slowest moving pointer */
- /* med, array of intermediate pointers */
- /* fast, array of fastest moving pointers */
- /* bytes, size of data type for final array */
- /* Function call example: */
- /* double ***buffer; */
- /* int nslo, *nmed, *nfst; */
- /* ... allocate and fill arrays nmed and nfst */
- /* buffer = (double ***) dim3D( nslo, nmed, nfst, sizeof(double) ); */
- /* if (buffer == NULL) { do_disaster_recovery(); } */
- /* Free using free3D(). */
- /* Always check for NULL return buffer - it's easy to chew up 64K! */
-
- void *** a;
- register int i, j;
-
- /* allocate space for an array of 'slow' pointers: */
- a = (void ***)calloc( slow, sizeof(void **) );
- if (a == NULL) { return(NULL); } /* check after every allocation */
- else
- {
- for (i = 0; i < slow; i++) /* for each 'slow' pointer */
- {
- /* allocate space for an array of med void * values */
- a[i] = (void **)calloc( med[i], sizeof(void *) );
- if (a[i] == NULL)
- {
- free3D( &a, slow, med );
- return(NULL);
- }
- for (j = 0; j < med[i]; j++) /* for each med pointer */
- {
- a[i][j] = (void *)calloc( fast[j], bytes );
- if (a[i][j] == NULL)
- {
- free3D( &a, slow, med );
- return(NULL);
- }
- }
- }
- return(a); /* return *** to void */
- }
- }
-
- void free3D(void **** a, int slow, int *med)
- {
- /* Frees memory allocated by dim3D() */
-
- /* usage:
- double *** buffer;
- int nslo, *nmed, *nfst;
- ... allocate and fill arrays nmed and nfst
- buffer = (double ***)dim3D( nslo, nmed, nfst, sizeof(double) );
- free3D( &buffer, nslo, nmed );
- free( nmed );
- free( nfst );
- */
-
- register int j, i;
-
- for(i = slow-1; i >= 0; i--) /* starting with last row */
- {
- for (j = med[i]-1; j >= 0; j--)
- {
- if ((*a)[i][j]) free ((*a)[i][j]); /* free array */
- (*a)[i][j] = NULL; /* & set to NULL until all freed. */
- }
- if ((*a)[i]) free ((*a)[i]);
- (*a)[i] = NULL;
- }
- if (*a) free (*a); /* free the pointer to pointer */
- *a = NULL;
- }
-
- int main( void )
- {
- /* sample driver program */
- double *** buffer;
- int nslo, *nmed, *nfst;
- register int i, j, k;
-
- /* You fill in these arbitrary assignments at run-time: */
- nslo = 2; /* arbitrary assignment number of levels */
- nmed = (int *)calloc( nslo, sizeof(int) );
- nmed[0] = 3; /* arbitrary assignment number of levels */
- nmed[1] = 2; /* arbitrary assignment number of levels */
- nfst = (int *)calloc( (3+2), sizeof(int) );
- nfst[0] = 4; /* arbitrary assignment number of levels */
- nfst[1] = 2; /* arbitrary assignment number of levels */
- nfst[2] = 3; /* arbitrary assignment number of levels */
- nfst[3] = 4; /* arbitrary assignment number of levels */
- nfst[4] = 3; /* arbitrary assignment number of levels */
-
- /* So, there are arbitrarily 2 levels of variable nslo,
- 3 and 2 levels of nmed at the two levels of nslo, and
- 4, 2, and 3 levels of nfst at the 3 levels of nmed[0], and
- 4 and 3 levels of nfst at the 2 levels of nmed[1].
- */
-
- buffer = (double ***)dim3D( nslo, nmed, nfst, sizeof(double) );
- if (buffer == NULL) exit (-1);
- for (i = 0; i < nslo; i++)
- for (j = 0; j < nmed[i]; j++) /* notice nmed[i], not nmed[j] */
- for (k = 0; k < nfst[j]; k++) /* nfst[j], not nfst[k] */
- buffer[i][j][k] = (double)rand(); /* random double */
- for (i = 0; i < nslo; i++)
- {
- printf("\n\nFactor nslo level %i\n", i);
- for (j = 0; j < nmed[i]; j++) /* notice nmed[i], not nmed[j] */
- {
- printf("\nFactor nmed level %i\n", j);
- for (k = 0; k < nfst[j]; k++) /* nfst[j], not nfst[k] */
- printf("%lf ", buffer[i][j][k]);
- }
- }
- free3D( (void ****)&buffer, nslo, nmed );
- free( nmed );
- free( nfst );
- exit (0);
- }
-
-
-
- Doug Fitts
- University of Washington, Seattle
- Internet: dfitts@u.washington.edu
-