[comp.lang.c] Need help with pointer to array

hsgj@batcomputer.UUCP (02/08/87)

An application I have requires an array to hold filenames.  Each element
of this array must be 32 chars long, and I would like 16 elements.
I used to be using:
     static char fnames[16][32];

However, I decided it would be better to malloc this space instead of
having it static.  How do I declare a pointer to a two-d array?
My new version is:
     char *fnames;                    /* What is correct declaration? */
     fnames = malloc(16*32);
     GetFileNames(fnames);
     for (i = 0; i < 16; i++)
        printf("%s\n",fnames[i*32]);  /* this is wrong, no? */

I am sure that this is bad practice, and would like to be informed
of the 'correct' way to do this.

==> If you are kind enough to reply, please do so via mail. <==
==> This is because I am quite far behind in comp.lang.c.   <==

-- Dan Green
-- 
ARPA:  hsgj%vax2.ccs.cornell.edu@cu-arpa.cs.cornell.edu
UUCP:  ihnp4!cornell!batcomputer!hsgj   BITNET:  hsgj@cornella

thomas@spline.UUCP (02/08/87)

In article <132@batcomputer.tn.cornell.edu> hsgj@batcomputer.tn.cornell.edu (Dan Green) writes:
>However, I decided it would be better to malloc this space instead of
>having it static.  How do I declare a pointer to a two-d array?
>My new version is:
>     char *fnames;                    /* What is correct declaration? */
>     fnames = malloc(16*32);
>     GetFileNames(fnames);
>     for (i = 0; i < 16; i++)
>        printf("%s\n",fnames[i*32]);  /* this is wrong, no? */
>

If you want to dynamically allocate an array exactly the same shape you
had, you can do this:
	char (*fnames)[16][32];

	fnames = (char (*)[16][32])malloc(16*32*sizeof(char));
	GetFileNames(*fnames);
	for (i = 0; i < 16; i++)
	    printf("%s\n", (*fnames)[i]);

(This code compiles and lints on my HPUX system.  The sizeof(char) is
just sheer paranioa.)

Another way to do it (which would require modifying the declaration of
the argument to GetFileNames) is the following:

	char *fnames[16];
	
	for ( i = 0; i < 16; i++ )
	    fnames[i] = malloc(32*sizeof(char));
	GetFileNames(fnames);
	for ( i = 0; i < 16; i++ )
		printf("%s\n", fnames[i]);

...

	GetFileNames(fnames)
	char *fnames[16];

One advantage of this method is that you can easily allocate different
length strings for each element of the "array".

=Spencer   ({ihnp4,decvax}!utah-cs!thomas, thomas@utah-cs.ARPA)

chris@mimsy.UUCP (02/10/87)

In article <1911@utah-gr.UUCP> thomas%spline.uucp@utah-gr.UUCP
(Spencer W. Thomas) writes:
>If you want to dynamically allocate an array exactly the same shape you
>had, you can do this:
>	char (*fnames)[16][32];
> 
>	fnames = (char (*)[16][32])malloc(16*32*sizeof(char));
>	GetFileNames(*fnames);
>	for (i = 0; i < 16; i++)
>	    printf("%s\n", (*fnames)[i]);
>
>(This code compiles and lints on my HPUX system.  The sizeof(char) is
>just sheer paranioa.)

(You could use `sizeof (char [16][32])', or `sizeof (*fnames)'.)

This works, but considering that the original code was (presumably)

	char fnames[16][32];

	GetFileNames(fnames);
	for (i = 0; i < 16; i++)
		printf("%s\n", fnames[i]);

requires changing any occurrences of `fnames' to `(*fnames)'.  The
only advantage of the new code is that the storage for the names
can be allocated dynamically.  A more likely replacement is

	char (*fnames)[32];

	fnames = (char (*)[32]) malloc(16 * sizeof (char [32]));
	GetFileNames(fnames);
	for (i = 0; i < 16; i++)
		printf("%s\n", fnames[i]);

---which requires only the new declaration and allocation.

Of course, proper paranoia also includes checking the return
value from malloc():

	if ((fnames = (char (*)[32]) malloc(16 * sizeof (char [32))) == NULL)
		...		/* handle out of memory error */

Another annoying nit is that malloc() takes an unsigned argument,
while sizeof has type `size_t', which is not necessarily unsigned
(it is signed in 4BSD), requiring yet more casts.  (I would rather
have an unsigned `size_t'.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
UUCP:	seismo!mimsy!chris	ARPA/CSNet:	chris@mimsy.umd.edu