views:

142

answers:

3

I have declared an array char **arr; How to initialize the memory for the 2D char array.

A: 

There are two options for allocating an array of type char **

I've transcribed these 2 code samples from the comp.lang.c FAQ (which also contains a nice illustration of these two array types)

Option 1 - Do one allocation per row plus one for the row pointers.

char **array1 = malloc(nrows * sizeof(char *)); // Allocate row pointers
for(i = 0; i < nrows; i++)
  array1[i] = malloc(ncolumns * sizeof(char));  // Allocate each row separately

Option 2 - Allocate all the elements together and allocate the row pointers:

char **array2 = malloc(nrows * sizeof(char *));      // Allocate the row pointers
array2[0] = malloc(nrows * ncolumns * sizeof(char)); // Allocate all the elements
for(i = 1; i < nrows; i++)
  array2[i] = array2[0] + i * ncolumns;

You can also allocate only one memory block and use some arithmetic to get at element [i,j]. But then you'd use a char* not a char** and the code gets complicated. e.g. arr[3*ncolumns + 2] instead of arr[3][2]

Alexandre Jasmin
+3  A: 

One way is to do the following:

char **arr = (char**) calloc(num_elements, sizeof(char*));

for ( i = 0; i < num_elements; i++ )
{
    arr[i] = (char*) calloc(num_elements_sub, sizeof(char));
}

It's fairly clear what's happening here - firstly, you are initialising an array of pointers, then for each pointer in this array you are allocating an array of characters.

You could wrap this up in a function. You'll need to free() them too, after usage, like this:

for ( i = 0; i < num_elements; i++ )
{
    free(arr[i]);
}

free(arr);

I think this the easiest way to do things and matches what you need.

Ninefingers
I would use "*arr" instead of "char*" for the first calloc. And "**arr" instead of "char" for the calloc in the loop.
Andrei Ciobanu
By doing multiple allocations, the memory will not be continuous. Will it work fine while incrementing a pointer to access the value.
Ankur
@Ankur only withtin a *row* of the 2D array
Alexandre Jasmin
@Andrei So might I, (@Ankur - this is to guarantee you don't mix up the types) but I think what I've done here is clearer for an explanation.
Ninefingers
+3  A: 

You might be better off with a one dimensional array:

char *arr = calloc(WIDTH*HEIGHT, sizeof(arr[0]));

for (int y=0; y<HEIGHT; y++)
    for (int x=0; x<WIDTH; x++)
        arr[WIDTH*y+x] = 2*arr[WIDTH*y+x];

free(arr);
ndim