Assigning memory to double pointer?

Viewed 94794

I am having trouble understanding how to assign memory to a double pointer. I want to read an array of strings and store it.

    char **ptr;
    fp = fopen("file.txt","r");
    ptr = (char**)malloc(sizeof(char*)*50);
    for(int i=0; i<20; i++)
    {
       ptr[i] = (char*)malloc(sizeof(char)*50);
       fgets(ptr[i],50,fp);
    }

instead of this I just assign a large block of memory and store the string

  char **ptr;
  ptr = (char**)malloc(sizeof(char)*50*50);

would that be wrong? And if so why is it?

8 Answers

Your second example is wrong because each memory location conceptually would not hold a char* but rather a char. If you slightly change your thinking, it can help with this:

char *x;  // Memory locations pointed to by x contain 'char'
char **y; // Memory locations pointed to by y contain 'char*'

x = (char*)malloc(sizeof(char) * 100);   // 100 'char'
y = (char**)malloc(sizeof(char*) * 100); // 100 'char*'

// below is incorrect:
y = (char**)malloc(sizeof(char) * 50 * 50);
// 2500 'char' not 50 'char*' pointing to 50 'char'

Because of that, your first loop would be how you do in C an array of character arrays/pointers. Using a fixed block of memory for an array of character arrays is ok, but you would use a single char* rather than a char**, since you would not have any pointers in the memory, just chars.

char *x = calloc(50 * 50, sizeof(char));

for (ii = 0; ii < 50; ++ii) {
    // Note that each string is just an OFFSET into the memory block
    // You must be sensitive to this when using these 'strings'
    char *str = &x[ii * 50];
}
 char **ptr;
    fp = fopen("file.txt","r");
    ptr = (char**)malloc(sizeof(char*)*50);
    for(int i=0; i<50; i++)
    {
       ptr[i] = (char*)malloc(sizeof(char)*50);
       fgets(ptr[i],50,fp);
    }

fclose(fp);

may be your typo mistake but your loop should be of 50 instead of 20 if you are looking for 50 x 50 matrix. Also after allocation of memory mentioned above you can access the buffer as ptr[i][j] i.e in the 2D format.

A double pointer is just a pointer to another pointer. So you can allocate it like this:

char *realptr=(char*)malloc(1234);
char **ptr=&realptr;

You have to keep in mind where your pointer is stored at (in this example the double pointer points to a pointer variable on the stack so it's invalid after the function returns).

i will give one example, which might clear of the doubt,

char **str;                              // here its kind a equivalent to char *argv[]
str = (char **)malloc(sizeof(char *)*2)  // here 2 indicates 2 (char*)
str[0]=(char *)malloc(sizeof(char)*10)   // here 10 indicates 10 (char)
str[1]=(char *)malloc(sizeof(char)*10)   // <same as above>

strcpy(str[0],"abcdefghij");   // 10 length character 
strcpy(str[1],"xyzlmnopqr");   // 10 length character

cout<<str[0]<<endl;    // to print the string in case of c++
cout<<str[1]<<endl;    // to print the string in case of c++

or

printf("%s",str[0]);
printf("%s",str[1]);  

//finally most important thing, dont't forget to free the allocated mem
free(str[0]);
free(str[1]);
free(str);

well, this is how I do it:

#include <stdlib.h>

int main(void)
{
    int i = -1; // just a counter
    int j = 5; // how many strings
    char *s[j];
    while(++i < j)
        s[i] = malloc(sizeof(char*)); // allocating avery string separately
    return (0);
}

this also works:

char **allocate(int lines)
{
    int i = -1;
    char **s = malloc(sizeof(char *) * lines); // allocating lines
    while (++i < lines)
    {
        s[i] = malloc(sizeof(char*)); // alicating line
        scanf("%s", s[i]);
    }
    return (s);
}

int main(int ac, char *av[])
{
    int lines = 5; // how many lines
    char **s = allocate(lines);
    return (0);
}

Double pointer is, simply put, a pointer to a pointer, In many cases it is used as an array of other types.

For example, if you want to create an array of strings you can simply do:

char** stringArray = calloc(10, 40);

this will create an array of size 10, each element will be a string of length 40.

thus you can access this by stringArray[5] and get a string in the 6th position.

this is one usage, the others are as mentioned above, a pointer to a pointer, and can be allocated simply by:

char* str = (char*)malloc(40);
char** pointerToPointer = &str //Get the address of the str pointer, valid only in the current closure.

read more here: good array tutorial

Related