memory allocation for array of pointers - c

I need to allocate memory for a pointer which needs to be used as a 2d array.I know how to allocate memory for char pointers and int pointers I am confused how memory is allocated of a array of pointers.A pictorial representation of the reason would be very helpful,also is the code below fine?
char *names[5];
for(i=0;i<5;i++)
{
names[i]=(*char)malloc(sizeof(char));
}

No, this is not because you are allocating the array assuming a dimension of just 1 element of primitive type char (which is 1 byte).
I'm assuming you want to allocate 5 pointers to strings inside names, but just pointers.
You should allocate it according to the size of the pointer multiplied by the number of elements:
char **names = malloc(sizeof(char*)*5);
You don't need to allocate them one by one with a loop. Note that you need to specify that it is a pointer-of-pointers by using **

What you're doing is allocating space for 5 chars. You could write this and it'll have the same result:
char *names = (char *)malloc(sizeof(char) * 5);
If you want to have an array of pointers, I think this'd be the best code
char **names = (char **)malloc(sizeof(char *) * 5);
I'm not a super-coder, but as what I now, this is the right solution.

Also, in short you can do the following too in this case for allocating storage for five characters
names = (char*)malloc(5 * sizeof(char))

Emphisizing what Jack said in in the end: his code works only if the array is declared as a pointer-of-pointers by using **.
When the array is declared as
char *names[5];
I guess the right way of allocating memory is almost as Ak1to did, but multiplying by the wanted size of the string of chars:
char *names[5];
for(i=0;i<5;i++)
{
names[i]=(char *)malloc(sizeof(char)*80);
}
else the compiler throws an error about incompatible types.

Related

If I am reducing the size of a char ** pointer using realloc, does it internally frees up the individual char * pointers of the reduction size

I am trying to reduce the size of a char ** double pointer using realloc.
First the char ** pointer is allocated using malloc and then the individual char* pointers as given below.
char **first= (char**)malloc(num*sizeof(char*));
char **last=(char**)malloc(num*sizeof(char*));
for(int i=0;i<num;i++)
{
//each individual pointer holds 20 characters
first[i]=(char*)malloc(20*sizeof(char));
last[i]=(char*)malloc(20*sizeof(char));
}
Now after some operations, I want to reduce the size of first and last by one counter value where counter is less than num.
Purpose is to free last counter number of records.
If I do the following
//Freeing up internal pointer memories
i = 0;
while (i<counter)
{
free(first[num1-1 - i]);
free(last[num1-1-i]);
i++;
}
//Reducing the size of the double pointer using realloc
first = (char **)realloc(first, (num1-counter) * sizeof(char *));
last = (char **)realloc(last, (num1-counter) * sizeof(char *) );
After this if I print the records
for(i=0; i<num - counter; i++){
printf("First Name: %s ",first[i]);
printf("Last Name: %s ",last[i]);
}`
The last record seems to be corrupted.
If I just perform the following and do not free the individual char * pointers, it works fine.
first = (char **)realloc(first, (num1-counter) * sizeof(char *));
last = (char **)realloc(last, (num1-counter) * sizeof(char *) );
My question is does realloc of a double pointer to reduce the size, internally frees up the internal pointers and as I am doing both, it is some how corrupting the memory?
To answer your question: No, it doesn't.
Freeing the nested pointers in a char ** might be rude if the pointer is still in use somewhere else.
The C compiler doesn't follow memory pointers around, nor does it count object references, so it's up to you to free (or keep) the allocated memory of the nested strings within the char **.
As for the example code itself, it seems to have issues, but these were described in the comments to your question.

Assign the values of an array to a pointer

I am first concatenating a series of elements in an auxiliary char array to then assign the concatenated array to the pointer. The problem comes when assigning this char array to the pointer, where it produces a segmentation fault.
My approach was the following one:
char aux_name [12];
char * name = (char *) malloc(sizeof(char)*13);
int i;
for(i = 0; i < 5; i++){
sprintf(aux_name, "id_%i", i);
*name = (void *) (intptr_t) aux_name; //Conflict line
//Do something with variable name (it is required a pointer)
}
You don't assign a pointer value to an already malloc()-ed pointer, you'll be facing memory-leak there. You have to use strcpy() to achieve what you want.
OTOH, if you don't allocate memory dynamically, then you can assign the pointer like
name = aux_name;
That said,
I am first concatenating a series of elements in an auxiliary char array
Well, you're not. you're simply overwriting the array every time in every iteration. What you need to do is
Collect the return value of sprintf() every time.
next iteration, advance the pointer to buffer by that many locations to concatinate the new input after the previous one.
Note / Suggestion:
do not cast the return value of malloc() and family in C.
sizeof(char) is guranteed to be 1 in c standard. You don't need to use that, simply drop that part.
You can't do that, and you don't really need to, this would work
size_t nonConstanSizeInBytes = 14;
char *name = malloc(nonConstanSizeInBytes);
snprintf(name, 13, "id_%i", i);

Dynamic memory allocation for pointer arrays

I'm am trying to write a program that reads in a series of strings from a text file and stores these in an array of strings, dynamically allocating memory for each element. My plan was to store each string in an array using a pointer and then grow the array size as more were read in. I am having trouble to understand why my test code below is not working. Is this a workable idea?
char *aPtr;
aPtr =(char*)malloc(sizeof(char));
aPtr[0]="This is a test";
printf("%s",aPtr[0]);
In C a string is a char*. A dynamic array of type T is represented as a pointer to T, so for char* that would be char**, not simply a char* the way you declared it.
The compiler, no doubt, has issued some warnings about it. Pay attention to these warnings, very often they help you understand what to do.
Here is how you can start your testing:
char **aPtr;
int len = 1; // Start with 1 string
aPtr = malloc(sizeof(char*) * len); // Do not cast malloc in C
aPtr[0] = "This is a test";
printf("%s",aPtr[0]); // This should work now.
char *str; //single pointer
With this you can store one string.
To store array of strings you Need two dimensional character array
or else array of character pointers or else double pointer
char str[10][50]; //two dimensional character array
If you declare like this you need not allocate memory as this is static declaration
char *str[10]; //array of pointers
Here you need to allocate memory for each pointer
loop through array to allocate memory for each pointer
for(i=0;i<10;i++)
str[i]=malloc(SIZE);
char **str; //double pointer
Here you need to allocate memory for Number of pointers and then allocate memory for each pointer .
str=malloc( sizeof(char *)*10);
And then loop through array allocate memory for each pointer
for(i=0;i<10;i++)
str[i]=malloc(SIZE);
char * aPtr;
is as pointer to a character, to which you allocated memory to hold exactly 1 character.
Doing
aPrt[0] = "test";
you address the memory for this one characters and try to store the address of the literal "test" to it. This will fail as this address most likley is wider then a character.
A fix to your code would be to allocate memory for a pointer to a character.
char ** aPtr = malloc(sizeof(char *));
aPtr[0] = "test";
printf("%s", aPtr[0]);
Are more elegant and more over robust approach would be to allocate the same (as well as adding the mandatory error checking) by doing:
char ** aPtr = malloc(sizeof *aPtr);
if (NULL == aPtr)
{
perror("malloc() failed");
exit(EXIT_FAILURE);
}
...
You are doing it totally wrong. The correct version of your code should be like this:
int main ()
{
char *aPtr;
aPtr =(char*)malloc(20*sizeof(char));
aPtr ="This is a test";
printf("%s",aPtr);
}
You can use pointer array. if you want to store multiple string. Yes I know using for loop will be easy. But I am trying to explain in simple way even a beginner can understand.
int main ()
{
char *aPtr[10];
aPtr[0] =(char*)malloc(20*sizeof(char));
aPtr[0] ="This is a test";
aPtr[1] =(char*)malloc(20*sizeof(char));
aPtr[1] ="This is a test2";
printf("%s\n%s\n",aPtr[0],aPtr[1]);
}

Changing a static array to a dynamic one with minimal changes?

I have a C code that creates an array of char pointers as the following:
char* arr[100];
I use each element in this array to point to some string that is being calculated by another function. So basically arr[0] would point to string1 and arr[1] to string2, etc.
This works just fine. However I'm now asked to be more flexible by having the user to specify the number of strings as a parameter.
How can I do this with minimal changes to my code? I understand that I need to use malloc. However I'm getting a lot of warnings in all of the assignment statements I had before. I changed the declaration of the array as the following:
char* arr = (char*)malloc(n * sizeof(char*)); //where n is provided by user
I thought that I only needed to change the declaration. Now all of the assignment statements are giving warnings ("assignment makes integer from pointer without a cast"). The following is an example of an assignment statement:
arr[i] = str; //where str is defined as char* and is calculated by another function
Am I missing something here?
If you're looking to create an array of char *, you need a char **arr. Think of it as an array of char * -- if you had an array of int, you would have int *. Since you have an array of char *s, you need char **.
char** arr = malloc(n * sizeof(char*));
You are declaring arr as a pointer to char: either a single string or, if you prefer, an array of chars.
To allocate an array of pointers, declare arr as
char **arr = malloc(n * sizeof(char *));
By the way, remove the cast: it is unnecessary in C. See also Question 7.7 in the comp.lang.c FAQ.
Don't forget that string is an array too (char *), so u will need array of pointers, which should look like this:
char** arr = (char**)malloc(n * sizeof(char*));
you want to declare arr as as char ** since you are pointing to an array of pointers. If you declare arr only as char * (not char ** or char *[]) you only have one "string".

pointer array with strings using malloc and buffer in C

I am stuck in how to fill a pointer array with strings using malloc. In debug i see that when i fill the 1st pointer of array with a string, when its about to go to next pointer in the array it pass the next string in both 1st and second element... seems like when i use ptr[i]=buff; the ptr keeps showing in the buff array.
#include<stdlib.h>
#include<string.h>
#define size 2 //array of 2 pointers
int main()
{
int i;
char *ptr[size];
char buff[80];
for (i=0;i<size;i++)
{
memset(buff, 0, sizeof(char) * 80);
printf("Enter name:\n");fflush(stdout);
scanf("%s",buff);
ptr[i]=(char*)malloc(strlen(buff));
//ptr[i]=buff; //that was the mistake
strncpy(ptr[i], buff, strlen(buff)); //->correct answer!
printf("length %d\n",strlen(buff));
}
for (i=0;i<size;i++)
{
printf("prt[%d]=%s\n",i,ptr[i]);fflush(stdout);
}
for (i=0;i<size;i++)
{
free(ptr[i]);
}
return 0;
}
Another weird question that i have has to do with the length of the arrays in general. When an array is declared for example a[10] the pointer a points to the first element of the array. What i do not understand is where the length is being stored!? is it the previous memory address of the pointer a? Is it before? Or does it have to do with the compiler only?
Thanks. i hope that wasnt too much i asked. :)
This:
ptr[i]=buff;
does not copy the string. It just copies a pointer. So not have you caused a memory leak (you have no way to access the memory you just allocated), but it messes your program up, because ptr[i] now points at buff, so every time you read a new string, it will appear to affect all elements of ptr[].
Do this instead:
strncpy(ptr[i], buff, BUF_SIZE);
Note also that it's considered bad practice to use gets; consider what would happen if the user were to type a string with more than 9 characters.
The following is incorrect:
ptr[i]=buff
You should use strcpy() instead of the assignment.
Otherwise you assign the same pointer to all elements of ptr, leak the malloc()ed memory, and try to free() things you haven't malloc()ed.

Resources