[comp.lang.c] Malloc and arrays...

eychaner@suncub.bbso.caltech.edu (Amateurgrammer) (03/04/91)

Warm up those flame guns!  It's time for Another Novice Question!

I know this is partly covered in the FAQ, but it didn't seem to have quite
the answer I want.
I know that if I malloc a chunk of memory, like so:
  char *bigmemory;
  bigmemory = (char *) malloc (OODLES_O_BYTES);
I can access the chunk of memory as though it were an array, like so:
  bigmemory [RIGHT_HERE] = SOME_CHARACTER;
(I hope I have this right. This should decompose to:
  *(bigmemory + RIGHT_HERE) = SOME_CHARACTER;
shouldn't it?)
So how can I access it as a 2D array, like so:
  bigmemory [RIGHT_HERE][RIGHT_NOW] = SOME_CHARACTER;
I know I could use, for example:
  *(bigmemory + RIGHT_HERE * SIZEOF_RIGHTNOW + RIGHT_NOW) = SOME_CHARACTER;
but all my previous code (which uses the 2D array) would then have to be
changed.  And it looks much nicer (when RIGHT_HERE and RIGHT_NOW are big,
nasty expressions) in 2D array format.
And don't flame me for "writing bad code"; it was written during a kinder,
gentler period.  I'm doing the best that I can, learning as I go along.
								-Glenn
:-)
Glenn Eychaner - Big Bear Solar Observatory - eychaner@suncub.bbso.caltech.edu
"You Have the Right to Remain DEAD."
					-The Simpsons

dave@cs.arizona.edu (Dave P. Schaumann) (03/04/91)

In article <1991Mar3.172942.3116@nntp-server.caltech.edu> eychaner@suncub.bbso.caltech.edu writes:
>Warm up those flame guns!  It's time for Another Novice Question!
>
>I know this is partly covered in the FAQ, but it didn't seem to have quite
>the answer I want.
>[...]
>  bigmemory = (char *) malloc (OODLES_O_BYTES);
>I can access the chunk of memory as though it were an array, like so:
>  bigmemory [RIGHT_HERE] = SOME_CHARACTER;
>[becomes]
>  *(bigmemory + RIGHT_HERE) = SOME_CHARACTER;

Right.

>  bigmemory [RIGHT_HERE][RIGHT_NOW] = SOME_CHARACTER;

/* This requires that OODLES_O_BYTES is divisible by NUMBER_OF_ENTRIES_WANTED.
*/
char **two_d = malloc(NUMBER_OF_ENTRIES_WANTED * sizeof(char *))

  for( i = 0 ; i < NUMBER_OF_ENTRIES_WANTED ; i++ )
    two_d[i] = &bigmemory[ i * OODLES_O_BYTES / NUMBER_OF_ENTRIES_WANTED ]

Now you can say two_d[RIGHT_HERE][RIGHT_NOW] = SOME_CHARACTER
Provided I haven't made an Incredibly Stupid Mistake (TM), you should be
able to modify this to your needs.

-- 
		Dave Schaumann		dave@cs.arizona.edu
'Dog Gang'!  Where do they get off calling us the 'Dog Gang'?  I'm beginning to
think the party's over.  I'm beginning to think maybe we don't need a dog.  Or
maybe we need a *new* dog.  Or maybe we need a *cat*! - Amazing Stories

torek@elf.ee.lbl.gov (Chris Torek) (03/04/91)

In article <1991Mar3.172942.3116@nntp-server.caltech.edu>
eychaner@suncub.bbso.caltech.edu writes:
>Warm up those flame guns!  It's time for Another Novice Question!

Ah, but you at least checked the FAQ and thought a bit before you posted :-)

>[I can malloc a `1D array' but] how can I access it as a 2D array, like so:
>  bigmemory [RIGHT_HERE][RIGHT_NOW] = SOME_CHARACTER;
>I know I could use, for example:
>  *(bigmemory + RIGHT_HERE * SIZEOF_RIGHTNOW + RIGHT_NOW) = SOME_CHARACTER;
>but all my previous code (which uses the 2D array) would then have to be
>changed.  And it looks much nicer (when RIGHT_HERE and RIGHT_NOW are big,
>nasty expressions) in 2D array format.

Presumably `SIZEOF_RIGHTNOW' is an integer constant and will never
change (i.e., is fixed by the design; the algorithm only works on
M-by-31 arrays or some such).  For the following discussion, let us say
it is a `#define N 31'.  (It must in fact be some integer constant in
the `previous code' since C arrays must have fixed, integral sizes.)

Then:

	char (*p)[N];

declares p as a `pointer to array 31 of char'.  This means that p can
point to an `array 31 of char'; but moreover, just as `char *bigmemory'
can point to more than one of its base type (char), so too `p' can point
to more than one of its base type (array 31 of char).  If you want M
such arrays, all contiguous:

	p = (char (*)[N])malloc(M * sizeof *p);
	if (p == NULL) die("out of memory");

(or `p = (char (*)[N])malloc(M * sizeof(char [N]));' or ...malloc(M * N *
sizeof(char)) or malloc(M * N * 1) or malloc(M * N); these are all
equivalent).  Once you have done this:

	p[i][j]

(where 0 <= i < M and 0 <= j < N) is an individual `char'.  This works
because p[i] names the i'th object to which p points, i.e., the i'th
`array 31 of char'.  This array appears in a value context, so The Rule
applies; we take the corresponding `pointer to char' (which points to
the first character in the i'th `array 31 of char') and name its j'th
object.

Now, if the reason you are changing the code is that N is *not* a fixed
integer constant, all of this goes out the window.  Someone else has
posted a row-vector solution (and others appear in the FAQ), so I will
stop here.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov