Reputation:
I'm trying to understand how dynamically allocated arrays work in C 99. Anyways, I have the following code:
int main()
{
char** members=malloc(4*sizeof(*members));
*members=malloc(5);
*members="john";
*(members+1)="shouldn't work";
printf("%s \n",*members);
printf("%s",*(members+1));
return 0;
}
I thought I would get a run time error because I didn't allocate (members+1), but actually it did print both "john" and "shouldn't work", Also, it apperas the the *members=malloc(5) line wasn't necessary. Why?
Upvotes: 3
Views: 9301
Reputation: 6407
Because you have initialized pointer of type char**
with 4*sizeof(*members)
I think you are planning to store 4 strings, so recommendation is to allocate memory for all 4 strings, like:
char** members=malloc(4*sizeof(*members));
int i;
for(i = 0; i < 4; i++)
members[i] = malloc(100 + 1); // 100 is a max length of string
// actually length of each string can be different
or you can initialize all pointers with NULL and change them as needed (allocate or point to some allocated memory), e.g.:
char** members=malloc(4*sizeof(*members));
int i;
for(i = 0; i < 4; i++)
members[i] = NULL;
// ... somewhere ....
char str[] = "Some string";
members[2] = str;
// ... somewhere else ....
members[1] = malloc(20);
scanf("%19s", members[1]);
And in that case you can check with if(members[i] != NULL)
to identify items that point data.
Upvotes: 1
Reputation: 773
A few things:
malloc(4*sizeof(*members))
, it would be more clear if you were to use the type of the object you're trying to allocate space for, e.g. malloc(4 * sizeof(char *))
rather than using the name of a variable. edit: as cmaster has pointed out, this can cause problems if you change the type of the variable without changing the type in the malloc()
so take this advice with a grain of salt*members=malloc(5);
isn't necessary in your case, because your compiler has allocated space for the string "john"
for you already, and*members="john";
works by setting the pointer at index 0 of your string array to the address of the compiler allocated "john"
*(members+1)="shouldn't work";
actually does work because of the point mentioned in 3.*members="john";
-- you have lost the pointer to the memory you malloc(5)
'ed, so that memory is going to be leaked :)Upvotes: 1
Reputation: 2208
char** members=malloc(4*sizeof(*members));
this means you have created an array and allocated memory for four elements that can store the address of a string.
So if you remove the line *members=malloc(5); then also it will work.
int main()
{
char** members=malloc(4*sizeof(*members));
//*members=malloc(5);
*members="john";
*(members+1)="shouldn't work";
printf("%s \n",*members);
printf("%s",*(members+1));
return 0;
}
i.e. member can hold four members and each of them can hold the address of a string.
Upvotes: 2
Reputation: 6793
Your assignments aren't doing what you think they're doing. When you assign *members
or *(members+1)
, you're assigning the char*
to each string literal, not copying it to allocated (or not allocated) heap memory.
If instead you replaced your assignments with strcpy
, i.e.:
strcpy(*members, "john");
strcpy(*(members+1), "shouldn't work");
Then you will get an access violation on the second assignment but not the first. Likewise, the reason malloc(5)
appears to be unnecessary is because you reassign the pointer to point to the string literal, instead of copying the "john" string to the allocated memory.
Upvotes: 5