[comp.std.c] One Really St00pid Question

asldh@acad2.anc.alaska.edu (01/14/91)

  Welp, I hope that nobody out there is too offended, but I need to ask a
Really Stupid Question.  Ready?  I am writing in MS-DOS Turbo C or Microsoft C,
and I need to be able to pass the data contained in a two-dimensional char
array from one function to another.  I looked in all of my programming
references and found NOTHING on passing multi-dimensional arrays, and the
one-dimensional array method did not seem to work.  I have constructed a
workaround at the moment, which consists of declaring a global array large
enough to handle any of the arrays I need to pass, and then filling it as
needed.  However, this "solution" offends me -- it smells of old-time BASIC
methodology... :-}  Can anyone offer me a more elegant method?  I do not need
to alter the contents of the arrays (at present), but I do need to read them. 
Thanks in advance for listening to the ramblings of another lost soul...
(If this is the WRONG newsgroup, please direct your flames to alt.nul...
Thanks!)
 
 
@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!
#                             %                                            @
%     Lars D. Hedbor          ! The enduring and uninfringed freedom of    #
!       USAF, Inc.            @ humanity is among the very few things      %
@       Student at            # worth devoting your entire life to.        !
#          UAA                %                                            @
% asldh@acad2a.anc.alaska.edu !                 -Me, just this moment.     #
!                             @                                            %
@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!@#%!
   SysOp of the Observatory, (907) 277-3508, 3/12/24/9600, 8N1, Opus 1.14
              These opinions are not necessarily even mine!
                                                                      

rose@glacier.unl.edu (David Rosecrans) (01/22/91)

In <1991Jan13.130957.1@acad2.anc.alaska.edu> asldh@acad2.anc.alaska.edu writes:


>  Welp, I hope that nobody out there is too offended, but I need to ask a
>Really Stupid Question.  Ready?  I am writing in MS-DOS Turbo C or Microsoft C,
>and I need to be able to pass the data contained in a two-dimensional char
>array from one function to another.  I looked in all of my programming
>references and found NOTHING on passing multi-dimensional arrays, and the
>one-dimensional array method did not seem to work.  I have constructed a
>workaround at the moment, which consists of declaring a global array large
>enough to handle any of the arrays I need to pass, and then filling it as
>needed.  However, this "solution" offends me -- it smells of old-time BASIC
>methodology... :-}  Can anyone offer me a more elegant method?  I do not need
>to alter the contents of the arrays (at present), but I do need to read them. 
>Thanks in advance for listening to the ramblings of another lost soul...
>(If this is the WRONG newsgroup, please direct your flames to alt.nul...
>Thanks!)

Someone asked the question a few weeks ago and I sent I reply directly because
I thought that alot of people would respond with the same answer I would give
as it turnde out they all either said it couldn't be done (not true) or used
some variation on allocating space and doing the multi-dimensional addressing
themselves.  Though the last one is fine I think what I'll show here is cleaner
and easier to use once its set up. After the initial extra work of dynamically
allocating the space you can use it just like any other array.  Of course you
also should free the space once you are done.  Anyway here we go, and by the
way this does require that you be comfortable with how arrays and pointers
(which are almost interchangable) work in C.

Lets start with the following decleration.

int	**t;

This says that t is a pointer to a pointer to an int.  To graphically represent
this:

  ____     ____     ____
 | t*----->  *----->int |
 |____|   |____|   |____|

Since we can think of a pointer to an element as an array of the same type, so
t could also be an array of pointers to ints, and to carry it a bit farther
a pointer to an int is functionally similar to an array of ints, we are all
familiar with pointers to characters and arrays of characters being the same.

  ____    ____     ____ ____ ____ ____ ____
 | t*---->   *----> int| int| int|    |   .....
 |____|  |____|   |____|____|____|____|____
	 |   *-----> int| int|    |    |   ....
	 |____|    |____|____|____|____|____
	 |    |      .    .
	 |____|      .........
	 |    |      .    .
	 |____|      .........
	 |    |      .    .
	 |____|      .    .
	 | .  |      .    .
	 | .  |
	   .
	   .

The nice thing is that we can use it in the same way too.  If we say
t[3] we get the fourth element of what t points to.  That in itself is a 
pointer to an int so we can use the array index again, which will give us
t[3][3]  which actually gets an int.  So after we allocate the structure
the only thing strange is the decleration in passing it.  but that is easy
to generalize.  One '*' is a one-dimensional array, two '**' is a two
dimensional array and so on.  So enough pointer basics, here's malloc_2d
as an example of how to allocate multidimensional arrays it should be easy
to modify for any N and it may even generalize, but I've never needed more
then a 3d array so I've never tried it.

void **malloc_2d(int rows, int cols, size_t size)
  {
    void	**t;
    int		i;

    if ((t = (void **) malloc(rows * sizeof(void *))) == NULL)
      return NULL;
    for (i = 0; i < rows; i++)
      if ((t[i] = (void *) malloc(cols * size)) == NULL)
	return NULL;
    return t;
  }

You'll may want to free up what ever space is allocated when it fails to 
allocate the rows, but you will get the idea.  To use it:

.
.
.
.
int	**a = malloc_2d(4,5,sizeof(int));
int	**b = malloc_2d(4,5,sizeof(int));
int 	**c;

/* should check that malloc 2d worked and need to load something usefull
	in. */

c = add(a,b,4,5);
.
.
.
.
int **add(int **a, int **b, int rows, int cols)
  {
    int		**c = malloc_2d(rows,cols,sizeof(int));
    int		i;
    int		j;

    if (c != NULL)
      {
	for (i = 0; i < rows; i++)
	  for (j = 0; j < cols; j++)
	    c[i][j] = a[i][j] + b[i][j];
      }
    return c;
  }

So, thats it.  I hope it helps.  It is also pretty efficient at least
on machines were additions are faster than multiplies.

David Rosecrans
University of Nebraska/Lincoln
rose@fergvax.unl.edu
-----------------------------
Nothing cute shall appear here.