[comp.lang.c] Two Dimensional Arrays.

sam@lfcs.ed.ac.uk (S. Manoharan) (02/25/89)

Passing a 2-D array around different functions does not seem
nice, for one needs to declare the dimensions of the array in
each and every function. The only way to overcome this problem
is to use pointers instead of arrays. As an added advantage,
we can allocate the space at runtime.

In order to represent a 2-D array, I came up with the following:

typedef union {
   double dv;
   long   lv;
} mat_decl;
typedef enum { _double, _long } mat_type;

mat_decl *MatRead(FILE *fp, int n, int m, mat_type type);
  /* Read matrix of type mat_type, size nXm from FILE ; return 
     pointer to the first element */ 
void MatPrint(FILE *fp, mat_decl *A,int n, int m, mat_type type);
  /* Print matrix A of type mat_type, size nXm to FILE */ 

We can access the (i,j) the element of the array M  as _M(i,j):
#define _M(i,j)   ((M + m*i + j)->lv)
    /* m: no. of columns */

The use of union is simply to make the matrix functions general.
For example:

mat_decl *MatRead(fp,n,m,type)
FILE *fp; int n,m; mat_type type;
{
   int j; mat_decl *A, *head;
   char *calloc();

   if ( ( A = (mat_decl *)calloc((unsigned) (n*m),sizeof(mat_decl)) )
      == (mat_decl *)0 ) return ( (mat_decl *) 0);

   head = A;
   for ( j = 0; j < n*m; ++j, ++A )
      switch ( type ) {
      case _double:
         fscanf(fp,"%lf",&(A->dv));
         break;
      case _long:
         fscanf(fp,"%ld",&(A->lv));
         break;
   }
   return head;
} /* EnMatRead */

Now, coming to the query, is there a better/elegant way of coding
an array sothat one can use his matrix functions ( say, transpose,
inverse, read, write, ... ) for all array types ( double, long, .. )
and sizes?

---
sam%uk.ac.edinburgh.lfcs%uk.ac.ucl.cs.nss@net.cs.relay

ark@alice.UUCP (Andrew Koenig) (02/27/89)

In article <1474@etive.ed.ac.uk>, sam@lfcs.ed.ac.uk (S. Manoharan) writes:
> Passing a 2-D array around different functions does not seem
> nice, for one needs to declare the dimensions of the array in
> each and every function. The only way to overcome this problem

Actually, you only need to declare the second dimension.

This is discussed in some detail in chapter 3 of
-- well, never mind.
-- 
				--Andrew Koenig
				  ark@europa.att.com

gwyn@smoke.BRL.MIL (Doug Gwyn ) (02/28/89)

In article <1474@etive.ed.ac.uk> sam@lfcs.ed.ac.uk (S. Manoharan) writes:
>Passing a 2-D array around different functions does not seem
>nice, for one needs to declare the dimensions of the array in
>each and every function. The only way to overcome this problem
>is to use pointers instead of arrays.

You can also pass around descriptors by value, not just by reference.

>Now, coming to the query, is there a better/elegant way of coding
>an array sothat one can use his matrix functions ( say, transpose,
>inverse, read, write, ... ) for all array types ( double, long, .. )
>and sizes?

Unless you use self-describing structures, you cannot possibly cover
ALL array types.  And I would be hard put to say what some of the
operations mean for some types of array.  To take a simple example,
what is the "inverse" of an integer array?  (Probably not an integer
array.)  In some cases more than one definition is possible, depending
on context.  For Boolean matrices, the transitive closure is an
important operation that has no counterpart for real-number matrices.
And so on.  The point of all this is, one should implement the most
commonly useful operations for the most common data types, and not
worry too much about excessive generality.