home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 14 / CD_ASCQ_14_0694.iso / maj / 653 / amalloc.c < prev    next >
C/C++ Source or Header  |  1994-04-03  |  4KB  |  125 lines

  1. /*
  2.  
  3. AMALLOC - multi-dimensional malloc()
  4.  
  5. Allocates a multidimensional array dynamically, at runtime, so that
  6.   1: its elements can be accessed using multiple indirection
  7.   2: it can be deallocated using a call to the standard free() function
  8. Note: On PC's the max array size is 64K
  9.  
  10. Paul Schlyter, 1992-02-09.  Released to the public domain.
  11.  
  12. */
  13.  
  14.  
  15. #include <stdlib.h>
  16. #include <stdarg.h>
  17. #include <string.h>
  18.  
  19.  
  20. #define MAXDIMS  5              /* Defines the maximum number of dimensions */
  21. #define MAXSIZE  ((size_t) -1L) /* Maximum size of array */
  22.  
  23.  
  24. void *amalloc( int esiz, void *initval, int dims, ... )
  25. /*
  26.  *  Input:   esiz     size of each array elements, as given by sizeof
  27.  *           initval  pointer to initial value. NULL ==> zero fill
  28.  *           dims     number of dimensions: 1..MAXDIMS (5)
  29.  *           ...      number of elements in each dimension (int's)
  30.  *
  31.  *  Returns:  NULL    error: out of memory, or illegal parameters
  32.  *                    otherwise base pointer to array
  33.  */
  34. {
  35.       unsigned int dim[MAXDIMS], accdim[MAXDIMS];
  36.       va_list ap;
  37.       int i, j;
  38.       long int totsiz;
  39.       void **q;
  40.       char *p, *r, *s;
  41.  
  42.       if (dims < 1  ||  dims > MAXDIMS)
  43.             return NULL;
  44.  
  45.       memset(dim, 0, sizeof(dim));          /* Read dimension numbers */
  46.       memset(accdim, 0, sizeof(accdim));
  47.       va_start(ap, dims);
  48.       dim[0] = accdim[0] = va_arg(ap,int);
  49.       for (i = 1; i < dims; i++)
  50.       {
  51.             dim[i] = va_arg(ap,int);
  52.             accdim[i] = accdim[i-1] * dim[i];
  53.       }
  54.       va_end(ap);
  55.  
  56.                                             /* Compute total array size */
  57.       totsiz = esiz * accdim[dims-1];       /* Data size */
  58.  
  59.       for (i = 0; i < dims - 1; i++ )       /* Add space for pointers */
  60.             totsiz += sizeof(void *) * accdim[i];
  61.  
  62.       if (totsiz > MAXSIZE)                 /* Exit if totsiz too large */
  63.             return NULL;
  64.  
  65.       p = malloc((size_t) totsiz);          /* Allocate memory */
  66.       if (p == NULL)                        /* Out-of-memory   */
  67.             return NULL;
  68.       memset(p, 0, (unsigned int) totsiz);  /* Zero out allocated memory */
  69.       q = (void **) p;
  70.  
  71.       if (dims == 1)
  72.             r = (char *) q + esiz * accdim[0];
  73.  
  74.       for (i = 1; i < dims; i++)            /* Fill in pointers */
  75.       {
  76.             int siz;
  77.             int accd = accdim[i-1], d = dim[i];
  78.  
  79.             siz =  i == dims-1 ? esiz : sizeof(void *);
  80.  
  81.             r = (char *) q + sizeof(void *) * accd;
  82.             for (j = 0; j < accd; j++)
  83.             {
  84.                   *q++ = r;
  85.                   r += siz * d;
  86.             }
  87.       }
  88.  
  89.       if (initval != NULL)
  90.       {
  91.             for (s = (char *) q; s < r; s += esiz)
  92.                   memcpy(s, initval, esiz);
  93.       }
  94.  
  95.       return p;
  96.  
  97. }  /* amalloc */
  98.  
  99.  
  100. #ifdef TEST   /* Test program */
  101.  
  102. #include <stdio.h>
  103.  
  104. main()
  105. {
  106.       static char init_d[8] = { 0x01,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF };
  107.       int init_i = 0x1111;
  108.       double *a   = amalloc( sizeof(double), init_d, 1, 4 );
  109.       double **b  = amalloc( sizeof(double), init_d, 2, 4, 5 );
  110.       double ***c = amalloc( sizeof(double), init_d, 3, 4, 5, 6 );
  111.       int ***d = amalloc( sizeof(int), &init_i, 3, 4, 5, 6 );
  112.       int i, j, k;
  113.  
  114.       for (i = 0; i < 4; i++)
  115.             for (j = 0; j < 5; j++ )
  116.                   for (k = 0; k < 6; k++ )
  117.                         d[i][j][k] = (i * 256) + (j * 16) + k;
  118.  
  119.       a = a, b = b, c = c;
  120.  
  121.       return 0;
  122. }
  123.  
  124. #endif
  125.