What's the difference between
struct mystruct *ptr = (struct test *)malloc(n*sizeof(struct test));
and
struct mystruct **ptr = (struct test *)malloc(n*sizeof(struct test *));
They both work fine, I'm just curious about the actual difference between the two. Does the first one allocate an array of structs, whereas the second one an array of struct pointers? The other way around? Also, which one has a smaller memory footprint?
The first allocates an array of struct, and the other allocates an array of pointers to struct. In the first case, you can write to fields by assigning ptr[0].field1 = value; right away, while in the second case you must allocate the struct itself before doing the actual writing.
It is OK to drop the cast of malloc result in C, so you could write
struct mystruct **ptr = malloc(n*sizeof(struct test *));
for (int i = 0; i != n ; i++) {
ptr[i] = malloc(sizeof(struct test));
}
ptr[0]->field1 = value;
...
// Do not forget to free the memory when you are done:
for (int i = 0; i != n ; i++) {
free(ptr[i]);
}
free(ptr);
I'm just curious about the actual difference between the two
The function malloc doesn't deal in structures or pointers. It only understands bytes. So the first allocates enough bytes for n struct test objects, which the second allocates enough space for n struct test * objects.
They both work fine
The way things look, the 2 would be used for wildly different things. For example, in the second case, you'd have to allocate memory for each ptr[i] element.
Also, which one has a smaller memory footprint
You can answer that yourself if you print sizeof(struct test) and sizeof(struct test *). But again, they're different things, with different purposes. Which has a smaller footprint, a tractor or a beetle ?
The first allocates an array of structs. The second allocates an array of pointers to structs (no memory for the structs themselves). So the second is smaller unless of course your struct is also very small like a pointer.
Related
I have come across an instance where memory is allocated dynamically to a char pointer within a struct in a way that does not make much sense to me, but - of course - works.
A similar question has been posted before. The answers, however, did not help me understand what is actually happening in the allocation process.
Here is the code example I found:
struct a_structure {
char *str;
struct a_structure *next;
};
Memory has been allocated in the following way:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
...
char *some_words="How does this work?";
ptr_start->str=(char *)malloc(strlen(some_words)+1);
strcpy(ptr_start->str, some_words);
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
...
I don't understand why malloc is used with the size of a pointer here. ptr_start is a pointer of type struct a_structure. That would mean it needs memory of size sizeof(struct a_structure) + the size of my string that hasn't been specified in the structure declaration. In the above example, however, malloc returns the address of yet another pointer pointing to a structure of type a_structure, am I right?
I don't understand why malloc is used with the size of a pointer here.
ptr_start is a pointer of type struct a_structure. That would mean it
needs memory of size sizeof(struct a_structure) + the size of my
string that hasn't been specified in the structure declaration
You are right. To create structure a_structure in order to manipulate it we need to allocate memory for whole structure.
(Unless the object has been ALREADY created and for whatever reason we need a dynamically allocated pointer holding pointer to that object).
but - of course - works.
The presented fragment of the program cannot work properly for the stated above reasons.
In the above example, however, malloc returns the address of yet
another pointer pointing to a structure of type a_structure, am I
right?
Yes, you are right.
This is also problematic:
ptr_start->next=(struct a_structure *)malloc(sizeof(struct a_structure *));
ptr_start->next can hold a pointer already. We typically do not need to allocate a pointer here. We would assign a pointer to the existing
structure or we would allocate memory for the whole structure.
See example:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct a_structure {
char *str;
struct a_structure *next;
};
struct a_structure * allocatePointer(void)
{
// ptr ptrToObj1Allocated points to allocted memory which can hold a ponter
struct a_structure * ptrToObj1Allocated = malloc(sizeof (struct a_structure *));
return ptrToObj1Allocated;
}
int main(){
// 1.
struct a_structure obj1; // structure a_structure has been allocated on the stack
struct a_structure * ptrToObj1 = & obj1; // points to the existing structure
char *some_words = "How does this work?";
ptrToObj1->str = malloc(strlen(some_words)+1);
if(ptrToObj1->str == NULL){printf("No enough memory\n"); return -1;}
strcpy(ptrToObj1->str, some_words); // copy the string
// now obj1 has its own copy of the string.
// 2.
// dynamically allocate another structure on the heap
// we want to allocate memory for the structure not just a memory to keep the pointer to the structure.
struct a_structure *obj2 = malloc( sizeof (struct a_structure)); // memory has been allocated to hold struct a_structure with 2 pointers
if(obj2 == NULL){printf("No enough memory\n"); return -2;}
char *words = "More words..";
obj2->str = malloc(strlen(words)+1);
if(obj2->str == NULL){printf("No enough memory\n"); return -3;}
strcpy(obj2->str, words); // copy the string
obj2->next = ptrToObj1; // points to the already existing object
//----
printf("String in obj1 is: %s\n", ptrToObj1->str);
printf("String in obj2 is: %s\n", obj2->str);
printf("obj2->next points to structure with string: %s\n", obj2->next->str );
// free the allocated memory:
free(ptrToObj1->str);
free(obj2->str);
free(obj2);
return 0;
}
Output:
String in obj1 is: How does this work?
String in obj2 is: More words..
obj2->next points to structure with string: How does this work?
Given that you have struct a_structure* ptr_start, this code is incorrect and does not work:
ptr_start=(struct a_structure *)malloc(sizeof (struct a_structure *));
It should have been:
ptr_start = malloc(sizeof *ptr_start);
The reason why it "seems to work" is because you invoked undefined behavior, and anything can happen. The program could seem to work one moment, then crash at another time.
This does however just allocate the struct itself. The pointers inside it will, like all pointers, point at memory allocated somewhere else. The following code with malloc for the string and strcpy() is one way to do so.
The last line is however incorrect for the same reason as pointed out above.
I am struggling to figure out how to allocate memory for my studentContent variable.
struct contactInfo {
char Name[101];
char Assignment[101];
char MarkDescription[101];
char feedBack[12][101];
};
struct contactInfo studentContent
I want to use malloc() to allocate memory for my structure variable. After the structure is filled I would like to reallocate the memory so I am only utilizing as much space within each field as I need to.
The first assignment sets ptr to the address of the local variable studentContent, however the next line overwrites that. It changes ptr to point to a dynamically allocated buffer with space for 2 instances of struct contactInfo.
If what you want is to have an array of struct contactInfo, and have the number of elements of that array increase as you have more instances of struct contactInfo to populate, you pass ptr to realloc with a size of n * sizeof *ptr, where n is the number of elements in the array.
struct contactInfo *tmp_ptr = realloc(ptr, n * sizeof *ptr);
if (tmp_ptr == NULL) {
perror("realloc failed");
exit(1);
}
ptr = tmp_ptr;
Note that you don't have to declare an instance of struct contactInfo (studentContent in your original code), just a pointer to one.
EDIT:
Based on your comment, since you just need a single instance to populate in order to read and write one chuck of data at a time, you don't need to use dynamic memory allocation. Just declare a single instance and overwrite the contents each time.
This is a structure that I am using:
struct nodeList//a node structure
{
int jump;
int config;
int level;
int shifts[200];
int shift_diff[200];
struct nodeList *next;
};
I want to create a 2D array of pointers that can be used to reference such a structure variable, ie, any element of that array can be assigned a pointer to a structure variable. I would prefer to create the array dynamically using malloc, if possible. Any pointers (pun unintended) would be appreciated.
First of all, please think twice about the program design. Do you really need a 2D array of pointers, each pointing to a struct, each struct containing a number of items? Those requirements are rather complex: if you can simplify them, your program will turn out much better.
Because with the current requirements, you'll notice that the pointer and array syntax will turn quite complex, which the requirements are to blame for, more so than the C language.
Consider things like using a 2D array of structs, or to use some sort of pointer-based ADT which makes sense for your given case (linked list, queue, graph, binary tree? etc etc).
That being said, a 2D array of pointers to struct:
struct nodelist* array[X][Y];
To allocate this dynamically, you need a pointer to a 2D array of pointers to struct:
struct nodelist* (*array_ptr)[X][Y];
Then assign this to a 2D array of pointers to struct, allocated dynamically:
array_ptr = malloc( sizeof(struct nodelist*[X][Y]) );
...
free(array_ptr);
Note that unless the 2D array is not allocated like above, in adjacent memory cells, it is not an array.
EDIT. Btw, if you wish to avoid the weird syntax that an array pointer will yield, there is a trick. With the code above you will have to address the array as
(*array_ptr)[i][j];
Meaning: "in the 2D array, give me item number [i][j]".
Had you omitted the inner-most dimension of the type, you could simplify this syntax:
struct nodelist* (*array_ptr)[Y]; // pointer to a 1D array
The malloc will be the same but you can now use it like this instead, which may be more intuitive:
array_ptr[i][j];
Meaning: "in array number i, give me item number j". You are here assuming there is an array of arrays in adjacent memory, which is true.
NODELIST ***pppNode, Node;
size_t Row = 5, Col = 5, i;
pppNode = malloc( sizeof(NODELIST **) * Row );
for(i = 0; i < Row; i++)
pppNode[i] = malloc( sizeof(NODELIST *) * Col );
pppNode[1][0] = &Node;
This is another way of dynamic allocation but as #Lundin said if it is not necessary change the design.
If I have a struct:
typedef struct A
{
char c[100];
}A;
Then I create a
sizeOfA = 5000;
A *list = (A*) malloc(sizeOfA * sizeof(A));
Is list[i] a pointer to a struct?
Or if I want a pointer to the struct, should I do
A **list = (A**) malloc (sizeOfA * sizeof(A*);
[EDIT]
Now let's say I created the list using A *list (which I did already). How would I create 5000 pointers and make them point to the elements on the list?
p0 -> list[0]
p1 -> list[1]
..
..
p[n] -> list[n]
After going back and forth a few times I noticed that for sorting the pointers help a lot.
To be fair I will post the edit above as a separate question.
After this statement:
A *list = (A*) malloc(sizeOfA * sizeof(A));
list is a pointer to the starting location of a memory block that can hold sizeOfA elements of type struct A. Thus, *list is of type struct A, and similarly, list[i] is of type struct A, not pointer to struct A (that would be list+i).
If you want list[i] to be a pointer to struct A, then your second piece of code would be the correct one, since you're allocating a memory location with enough space to hold sizeOfA pointers to struct A. Note that you are only allocating space to hold pointers, not actual struct A instances. Attempting to read list[i]->c will result in undefined behavior.
A *list = (A*) malloc(sizeOfA * sizeof(A));
Is list[i] a pointer to a struct?
No -- list is a pointer to an address in the heap, which is the start of a memory chunk that has size sizeOfA * sizeof(A). list[i] is the same thing as *(list + i), which is a dereference that will give you an actual A.
However..
A **list = (A**) malloc (sizeOfA * sizeof(A*);
Is list[i] a pointer to a struct?
Yup.
Good day!
I need to use malloc in creating a student list system.... In order to be efficient, our professor asked us to use it on a struct so i created a struct as follows:
struct student {
char studentID[6];
char name[31];
char course [6];
};
struct student *array[30];
everytime i add a record, that is when i use malloc...
array[recordCtr]=(struct student*)malloc(sizeof(struct student));
recordCtr++;
then i free it like this.
for(i = 0; i < recordCtr; i++){
free(array[i]);
}
Am i using malloc properly??? what is the effect if i free it like this instead of the loop above.
free(array);
Thanks in advance. Your opinion will be highly appreciated.
You are doing fine.
free(array); would be undefined behavior because array itself was not allocated via malloc therefore you can't free it and don't need to - the memory will be managed by the compiler.
A good tip is to always do:
type *something;
something = malloc(n * sizeof(*something));
This is because, if you change the type of something, you don't have to change all sorts of other code. And sizeof is really a compiler operation here, it won't turn into anything different at runtime.
Also, don't cast the void* pointer returned by malloc, there's no reason to do so in C and it just further ties your code together.
So in your case, don't do:
(struct student*)malloc(sizeof(struct student));
but
malloc(sizeof(**array));
There is nothing illegal about the way you are using malloc but this isn't a list, it's an array of pointers.
To use a list you do not fix the size in advance and have a pointer to the next element. You can either make this intrusive of non-intrusive.
For an intrusive list you put struct student * next in the declaration of student.
For a non-intrusive list you create another struct student_list_node which contains an instance of struct student and a pointer struct student_list_node * next;
This is an exacmple of the non-intrusive version:
struct student_list_node
{
struct student data;
struct student_list_node * next;
};
struct student_list_node * head;
struct student_list_node * tail;
struct student_list_node * addStudentToTail()
{
struct student_list_node * newnode = (struct student_list_node *)(malloc( sizeof(struct student_list_node ) );
/* check malloc did not fail or use a checking vesrion of malloc */
if( !tail )
{
head = tail = newnode;
}
else
{
tail->next = newnode;
tail = newnode;
}
return newnode; // which is also "tail"
}
int main()
{
struct student_list_node * node = addStudentToTail();
struct student * pstud = &node->data;
/* write to pstud student details */
}
If you do really want to use an array, you might want to make it an array of student rather than student * in which case you can use calloc rather than malloc
struct student * array = (struct student *)calloc( 30, sizeof( student ) );
Then using free(array) would be the correct way to dispose of it. You also have the option of allocating more if you need it later with realloc. (Be careful with this one: you must keep a copy of your original pointer until you know realloc succeeds).
The array itself isn't allocated on the heap. Assuming it's a global variable, it is allocated in global memory at program startup and doesn't need to be freed. Calling free on it will probably corrupt your program.
Your current solution is correct.
What you're doing is correct.
You can think of *array[30] as an array of 30 pointers
When you are allocating memory for each of those pointers, you'd also need to call free() on each of them.
Yes, you are using it correctly. There are better ways to organize the storage than this, but this will work. At least until you need more than 30 students...
Note that you must call free() with each pointer that is returned by malloc(). That means that your loop over the array of pointers is the correct approach for your chosen architecture.
Your attempt to call free on the array itself will not work. It invokes Undefined Behavior because you are passing a pointer (to the base of the array itself) to free() that did not come from a call to malloc().
Looks fine.
You could (if it fits your problem) allocate space for all 30 structs in one go
struct student *array = (struct student *)malloc(30*sizeof(struct student));
whhen you want to dispose of the space, you can then do
free(array)
What you have will work just fine. As others have mentioned, you've created an array of pointers on the stack and need to malloc and free each of them individually as you are doing.
However, you don't have to use malloc and free one struct at a time, you can do something like this:
int arraySize = 30;
student * ourArray = (student*)malloc(sizeof(student) * arraySize);
and a single free on the pointer will take care of it. with this pointer, you can still use the bracket notation and the compiler will understand that it's a typed pointer and behave appropriately, giving you essentially the same thing. Which method you use depends on if you need your array a dynamic size or not as well as personal preference.
Hope that helps some.
Initialize your array of pointer to struct student with NULL values
for(i = 0; i < recordCtr; i++){
array[i] = NULL;
}
Free memory if array[i] is not NULL
for(i = 0; i < recordCtr; i++){
if(NULL != array[i])
{
free(array[i]);
}
}
There's simple rule: Every malloc() should be paired with free() with pointer returned by malloc. Not less, not more.