views:

193

answers:

6

I was wondering how I could allocate (and De-Allocate) an array of char pointers (char*[64]) in C. I've looked around on the web for examples but they all focus on other datatypes or one dimension arrays.

+1  A: 

If you want a fixed-size array, chances are pretty fair that you don't need to use dynamic allocation at all. If you are going to allocate it dynamically, you'd do something like:

char **array;   
array = malloc(64 * sizeof(char *));

When it's time to free it, you'd just do like usual:

free(array);

Note, however, that if the pointers in the array point at anything (especially dynamically allocated memory) you need to deal separately with freeing that memory -- usually before you free the array of pointers.

Jerry Coffin
A: 

You allocate memory on the heap with malloc:

char** pPointers;
pPointers = malloc(sizeof(char*) * 64);

Now you have an array of 64 pointers to character(s).

You deallocate memory with this call:

free(pPointers);

You will probably assign values to your array:

pPointers[0] = "abc";
pPointers[1] = &cSampleCharVariable;
pPointers[2] = strdup("123");

Freeing this memory depends on what the pointers point to. In the samples above only pPointers[2] can be deallocated.

harper
What would I have to do to deallocate [0], and [1]?
Lienau
No. The compiler places the [0] string "abc" in the const memory section, you are not allowed to deallocate it. [1] is a pointer to an cSampleCharVariable that was already allocated before. If this is an object allocated with malloc, you must deallocate it somehow. But this is not related to this array of pointers.
harper
A: 

If you have the type given in your question:

char *foo[64];

Then you don't need to explicitly allocate memory for foo - it's a normal array. To allocate memory for the pointers in foo, just use a loop:

int i;

for (i = 0; i < 64; i++)
{
    foo[i] = malloc(somesize);
}

(You shouldn't really use the magic value 64 in the loop, though; either use a #define FOOSIZE 64, or use sizeof foo / sizeof foo[0] to determine the size of the array).

caf
+1  A: 

This is answered at The C FAQ.

Here is that code adapted for char* instead of int* with some example data.

#include <stdlib.h>

#define nrows 10
#define ncolumns 64

int main(int argc, char* argv[])
{

    int i;

     //allocate 10 char*
    char **array1 = (char**)calloc(nrows,sizeof(char*));
    for(i = 0; i < nrows; i++)      
    {
        //allocate 64 chars in each row
        array1[i] = (char*)calloc(ncolumns,sizeof(char));  
        sprintf_s(array1[i],numcolumns,"foo%d",i);
    }

    for(i=0;i<nrows;i++)
        printf("%s\n",array1[i]);

     //prints:
     //  foo0
     //  foo1
     //  ..
     //  foo9
     for(i=0;i<nrows;i++)
           free(array1[i]);

     free(array1);

    return 0;
}
Coleman
Actually I had planned on 64 char* (or 10 or whatever), But thanks. This is just what I need!
Lienau
The advantage of using calloc over malloc here is that it zeroes the memory at allocation time.So Coleman's use of calloc was a good defensive measure.An inadvertantly uninitialized pointer whose value is 0 is a much less dangerous bug than one whose value is unpredictable. Random pointers can lead to extremely hard to track down bugs.
pbernatchez
A: 

At the risk of being obvious (and less general than the other answers), sizeof ( char * [64] ) equals 64 * sizeof ( char * ), so you can just write p = malloc ( sizeof ( char * [64] ) ) to allocate the memory and free ( p ) to free it.

Pete Kirkham
A: 

Doing the 65 allocations of the accepted answer will work, but If you know the lengths of the char data ahead of time you can make it a hell of a lot faster by doing something like this.

Assume cItems is an int that is the number of elements in your array, say 64. Assume aItemSizes[] contains the lengths of the char data for each element in your array:

int iItem;
char **aItems, *pData; 

for (cbCharData=iItem=0; iItem<cItems ; iItem++)  
  cbCharData += aItemSizes[iItem];
aItems = (char**)malloc(sizeof(char*)*cItems + cbCharData); 
for (iItem=0, pData=&aItems[cItems] ; iItem<cItems ; pData+=aItemSizes[iItem], iItem++)  
  aItem[iItem] = pData;

Now aItem[iItem] points to a memory location that can handle up to aItemSizes[iItem] chars and you only needed one allocation, which is WAAAAAAAAAAAAAAAAAAAAAAAAAAY faster. I apologize for compile errors cuz i didnt test this. To free it you only free aItems.

johnnycrash