[comp.lang.c] 2d arrays

sasg0244@uxa.cso.uiuc.edu (Steven Arthur Sivier) (03/14/91)

i've always tried to avoid 2d arrays, but because of a library
function i need to call i need to use 2d arrays. the problem
is i have to malloc the 2d array. can i just malloc the array
to a char pointer and then use it as a 2d array? that is, if
the array has dimensions x by y can i use:
	char *array;
	array = malloc(x * y);
	array[0][0] = 'a'

also, inasmuch as i need to pass this array to a library function,
can i just send the pointer even though the function expects a
2d array?

sorry if this seems like a stupid question, but i usually just
kludge around the very few times i've needed multi-dimensional
arrays.

thanks
steve sivier
sasg0244@uxa.cso.uiuc.edu

pfeifer@alw.nih.gov (John Pfeifer) (03/14/91)

In article <1991Mar13.183807.23254@ux1.cso.uiuc.edu>, sasg0244@uxa.cso.uiuc.edu (Steven Arthur Sivier) writes:
|> 
|> i've always tried to avoid 2d arrays, but because of a library
|> function i need to call i need to use 2d arrays. the problem
|> is i have to malloc the 2d array. can i just malloc the array
|> to a char pointer and then use it as a 2d array? that is, if
|> the array has dimensions x by y can i use:
|> 	char *array;
|> 	array = malloc(x * y);
|> 	array[0][0] = 'a'

If I understand you correctly, no.  char[][] is an array of arrays, ie. **char  Try:
	char **array;
	array = malloc(x*sizeof(*char));
	for(i=0;i<x;i++)
		array[i] = malloc(y*sizeof(char));
 
|> also, inasmuch as i need to pass this array to a library function,
|> can i just send the pointer even though the function expects a
|> 2d array?

Yes.
See section A8.6.2 in K&R (2nd ed.)

-John
-- 
#include <stdsig.h>

        John Pfeifer                    internet: pfeifer@alw.nih.gov

	"The most creaative and holy of men are always quite mad.
	 It is simply a social thing as to wether one is sane or
	 _insane_."				-The Madonna Vampira

volpe@camelback.crd.ge.com (Christopher R Volpe) (03/14/91)

In article <1065@nih-csl.nih.gov>, pfeifer@alw.nih.gov (John Pfeifer) writes:
|>In article <1991Mar13.183807.23254@ux1.cso.uiuc.edu>,
sasg0244@uxa.cso.uiuc.edu (Steven Arthur Sivier) writes:
|>|> 
|>|> i've always tried to avoid 2d arrays, but because of a library
|>|> function i need to call i need to use 2d arrays. the problem
|>|> is i have to malloc the 2d array. can i just malloc the array
|>|> to a char pointer and then use it as a 2d array? that is, if
|>|> the array has dimensions x by y can i use:
|>|> 	char *array;
|>|> 	array = malloc(x * y);
|>|> 	array[0][0] = 'a'
|>
|>If I understand you correctly, no.  
|>char[][] is an array of arrays, ie. **char  Try:
  ^^^^^^^^                            ^^^^^^This is not the same thing as
  This is not valid C.                      an array of arrays.
                                        
|>	char **array;
|>	array = malloc(x*sizeof(*char));
|>	for(i=0;i<x;i++)
|>		array[i] = malloc(y*sizeof(char));
|> 
|>|> also, inasmuch as i need to pass this array to a library function,
|>|> can i just send the pointer even though the function expects a
|>|> 2d array?
|>
|>Yes.
|>See section A8.6.2 in K&R (2nd ed.)

No. The two step malloc method you used will allow you to reference the
object as if it were a 2D array, i.e., you can say "array[a][b]" and it
will work, but the storage is not laid out like a true 2D array that you
would declare with "char array[DIM1][DIM2];". If you pass your
"char **array" to a library routine that expects a true 2D array, it will
choke big time.
                                 
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

andand@cia.docs.uu.se (Anders Andersson) (03/20/91)

In <1065@nih-csl.nih.gov> pfeifer@alw.nih.gov (John Pfeifer) writes:

>In article <1991Mar13.183807.23254@ux1.cso.uiuc.edu>, sasg0244@uxa.cso.uiuc.edu (Steven Arthur Sivier) writes:
>|> 
>|> i've always tried to avoid 2d arrays, but because of a library
>|> function i need to call i need to use 2d arrays. the problem
>|> is i have to malloc the 2d array. can i just malloc the array
>|> to a char pointer and then use it as a 2d array? that is, if
>|> the array has dimensions x by y can i use:
>|> 	char *array;
>|> 	array = malloc(x * y);
>|> 	array[0][0] = 'a'

>If I understand you correctly, no.  char[][] is an array of arrays, ie. **char  Try:
>	char **array;
>	array = malloc(x*sizeof(*char));
>	for(i=0;i<x;i++)
>		array[i] = malloc(y*sizeof(char));
> 
>|> also, inasmuch as i need to pass this array to a library function,
>|> can i just send the pointer even though the function expects a
>|> 2d array?

>Yes.
>See section A8.6.2 in K&R (2nd ed.)

This is not so. Allocating with a loop does not give a 2d array, it gives
an array of (pointers to) arrays. It's easy to confuse them, since C uses
exactly the same syntax for both 2d arrays and arrays of arrays. Normally
the distinction is not crucial, but in this case, when a library module that
(presumably) is precompiled is involved the difference is important, since
the two approaces generate different memory lay-outs. If the library routine
really wants a 2d array, you must not use more than one call to malloc().
However, this is awkward, so it is a fair chance that the library routine
uses an array of arrays. If it does use a 2d array, the simplest way is to 
allocate a ordinary 1d array and use it as such, doing index calculation 
yourself, like:
       	char *array;
	array = malloc(x * y);
	array[0] = 'a'; 
	array[i * y + j] = 'b'; /* instead of array[i][j] */
where y is the width of the array (number of columns in a row). If y is known
in advance (e.g. 10 columns but unknown number of rows) this simplyfies to:
	typedef char row[y]; /* for clarity - a row of chars */
	row *array;
	array = (row *)malloc(sizeof(row) * x);
	array[0][0] = 'a';
	array[i][j] = 'b';

-Anders Andersson (andand@cia.docs.uu.se - mail just *might* get through, but
				           I wouldn't bet on it)