If the size of a structure pointer is 4 or say 8 bytes, how can it properly allocate the required memory for its data members in Dynamic Memory Allocation. This is my code:
#include<stdio.h>
typedef struct node{
char a[10];
char b[10];
char c[10];
int f;
struct node* next;
}node;
int main()
{
node* temp;
int d= sizeof(node *);
printf("Size of structure pointer = %d",d);
temp= (node*)malloc(sizeof(node*));
int c = sizeof(temp);
printf("Size of Temp = %d\n",c);
}
```````````````````
/*
Here both Temp and node* is having a size of 8 bytes.
But the size of the structure 'node' is 38 bytes(total size of the members).
So how can the pointer Temp allocate that much memory if its size is just 8 bytes ?
*/
Because you don't store data in pointers. Pointers point at data allocated elsewhere, hence the name "pointer". sizeof(node*) is wrong and the size of the pointer itself is irrelevant.
You should do
temp = malloc(sizeof *temp); // equivalent of sizeof(Node)
...
free(temp);
This is the pointer to the node struct, you don't need to allocate space for it. It can point to the node structure.
struct node *node_ptr;
If you want to store node structure at some pointer, you need to allocate space for the node structure NOT THE POINTER
node *node_data = malloc(sizeof(struct node));
You don't need to cast the result from the malloc, it is bad { see casting for malloc }
Pointer is just the pointer. It you are a tourist guide in the war museum and use the pointer to show the tank - what is the weight of the pointer in your hand? The weight of the wooden stick or the weight of the tank?
First lets understand about malloc:
Malloc is a function which allocates memory in a HEAP part of RAM. If we define a variable, usually it gets allocated in STACK part of RAM.
temp = (int*)malloc(n*sizeof(int));
this code allocates a memory in HEAP.
Now lets understand about ponters:
consider the following code.
int a;
int *p;
p=&a;
in the about line of code the pointer 'p' is storing the address of the variable 'a'.
Depending on the word length of your system(32bit or 64bit), the size of the pointer variable 'p' changes. It can be 2bytes or 4bytes or 8bytes. 8bytes is because in 64bit machine, "long int" can takes 8bytes.
Now lets understand about both pointers with structure:
struct value{
int a;
int b;
char c;
};
Since above code is a definition of structure, memory won't get allocated.
struct value s;
now the memory gets allocated in Stack.
struct value *s;
s = (struct value*)malloc(sizeof(struct value));
here the memory gets allocated in Heap.
Even though 's' is structure pointer it still stores the address of the whole structure 'value', it's size will be 4/8. It points to whole structure not the particular member of structure.
The general structure 's' will have the data part of all its members. So the size will be 5 or 9 depending of the machine and the padding.
struct s{
int a; /* 4 bytes */
char b; /* 1 byte */
/* 1 padding byte */
short c; /* 2 bytes */
};
Refer Data Structure Padding
Related
So I am learning about data structure stack in my college, howsoever I have some doubts in its implementation and the memory it occupies.
Below is a small code which I have written for it: -
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <stdbool.h>
struct stack
{
int *array;
int top;
int max_size;
};
struct stack createStack(int size)
{
struct stack *Stack = malloc(sizeof(struct stack)); //line 1
Stack -> max_size = size; //line 2
Stack -> top = -1; //line 3
Stack -> array = calloc(Stack -> max_size, sizeof(int)); //line 4
return *Stack;
}
int main()
{
int size; //Here lets say that size = 5
scanf("%d", &size);
printf("%ld", sizeof(createStack(size)));
return 0;
}
Here I have defined Stack through struct stack as seen below in this portion of the code: -
struct stack
{
int *array;
int top;
int max_size;
};
Now the memory which would be occupied by the above struct stack should be: -
8 bytes for int *array
4 bytes for int top
4 bytes for int max_size
Therefore total memory occupied\allocated should be 16 bytes.
Now lets come to the second portion of code which helps in creation of stack: -
struct stack createStack(int size)
{
struct stack *Stack = malloc(sizeof(struct stack)); //line 1
Stack -> max_size = size; //line 2
Stack -> top = -1; //line 3
Stack -> array = calloc(Stack -> max_size, sizeof(int)); //line 4
return *Stack;
}
Here in line 1 we have allocated the sizeof struct stack(16 bytes) in structure variable *Stack. Hence size of * Stack is 16 bytes.
In line 2 and in line 3 values are initialised.
Now my question come from line 4
In line 4 we allocated 20 bytes to int *array (considering max_size = 5)
Now shouldn't the size of structure variable *Stack be 28 bytes considering that int *array now occupies 20 bytes instead of 8 bytes ?
When I run the above code, it still mentions that the sizeof structure variable *Stack is 16 bytes. What am i missing here?
Now shouldn't the size of structure variable *Stack be 28 bytes considering that int *array now occupies 20 bytes instead of 8 bytes?
No. The size of array is still 8 bytes. It just contains the memory address of a separate chunk of memory that is 20 bytes in size. That separate chunk is not part of *Stack and does not contribute to its size.
In fact, sizeof(createStack(size)) does not call your function, so no memory is ever allocated. sizeof only cares about the type of its operand expression. Since createStack is declared as returning a struct stack, sizeof createStack(...) is equivalent to sizeof (struct stack). All of this is resolved at compile time.
Similarly, if you do
char arr[1000];
char *ptr = &arr[0];
then sizeof ptr is still 8 because ptr is declared as char * and sizeof (char *) is 8. That's all that matters.
By the way, if you were to actually call createStack, it would leak memory:
struct stack *Stack = malloc(sizeof(struct stack));
...
return *Stack;
The first line allocates memory and stores the address in Stack. However, this address does not leave the function. Only a copy of the struct itself is returned (via return *Stack). The program has now lost track of the pointer returned by malloc and can never free it.
Fix:
struct stack Stack;
Stack.max_size = size;
Stack.top = -1;
Stack.array = calloc(Stack -> max_size, sizeof(int));
return Stack;
The size of a structure is just the amount of memory used for the structure itself, not the memory for any things pointed to be members of the structure.
The fact that array is given a value that points to more memory does not change the structure or its size.
sizeof reports only the memory required for a particular object. It does not report all memory you have associated or linked to in some way.
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.
What will be the output of the program on a 32-bit machine (using GCC)? Explain.
#include<stdio.h>
int main() {
struct node {
int data;
struct node *link;
};
struct node *p, *q;
p = (struct node *) malloc(sizeof(struct node));
q = (struct node *) malloc(sizeof(struct node));
printf("%d, %d\n", sizeof(p), sizeof(q));
return 0;
}
The output shows
4, 4.
Is the above program related to structure member alignment padding and data packing?
No, you are just printing the size of the pointers. It's not related to the internal member layout of structures.
On a 32-bit system the stored addresses are always 32 bits big. If you're printing the size of a pointer you're basically just printing the size of the address it points to (32 Bit -> 4 Byte).
If you want to know the size of the struct do something like this:
struct node p;
struct node q = {4, &p};
printf("%zu, %zu\n", sizeof(p), sizeof(q));
Point 1 Use %zu format specifier to print the output of sizeof of type size_t .
Point 2 Note the type of p, it is struct node *, same as q.
So, essentially, sizeof(p) and sizeof(q) are exactly same as sizeof(struct node *), which, on your platform are 32 bit wide. As you're not considering a variable here, so the alignment and padding for the structure and members are neither relevant nor involved in this case.
That said, please see why not to cast the return value of malloc() and family in C.
No, it is not related to the structure member alignment padding and data packing.
Since it is a 32-bit machine the size of any pointer will be 4 bytes. Since p and q are of type struct node * i.e. pointer to struct node the result prints size of pointers p and q.
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.
My code is as follows,
#include<stdio.h>
struct data
{
int a ;
void *b;
};
int main()
{
struct data *d;
int *ptr;
int key=10000;
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
}
And i get a segmentation fault!! Any idea why?? Thanks in advance for any help
struct data *d merely declares a pointer. You have not allocated this struct anywhere. You need to either malloc it or declare it just as struct data d on the stack or globally.
The former can be done like this:
d = malloc(sizeof(struct data));
If you choose the latter, accessing b has to be written as d.b.
You are not allocating any memory for d. It likely points to an invalid memory area and so - segmentation fault.
You can solve this like so:
struct data *d = malloc(sizeof(*d));
You are getting segmentation fault at the line d->b=&key; Note that you have not allocated any memory location to the structure variable d. So d contains some garbage value, and d->b it trying to use that garbage address to dereference the pointer and get the component b. Here is where you get the segfault. Either statically allocate the struct variable, or use malloc to dynamically allocate it.
int main()
{
struct data *d;
int *ptr;
/* Here you are allocating memory to the
* pointer variable, which will be used to
* point to the structure type data
*/
d = malloc (sizeof (struct data));
int key=10000;
/* Now you can dereference the pointer
* and get any of the components of the
* structure, because 'd' contains a valid
* address.
*/
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
/* Good practice to free the memory location
* you have allocated. Not freeing will lead to
* memory leak in larger applications. After you
* free the memory location denoted by the address
* stored in 'd', you will not be anymore access
* the contents of it.
*/
free (d);
/* d->b; or d->a; is no more possible at this point
* as we have freed the memory pointed by 'd'
*/
}
Or you can use:
int main()
{
/* Not a pointer, statically allocated */
struct data d;
int *ptr;
int key=10000;
d.b=&key;
ptr=(int *)d.b;
printf("%d\n",*ptr);
}
So, it is not the typecasting of void * to int * that causes the segfault. Its the illegal memory reference of the pointer variable which you have used but not allocated/initialized.
The problem is that you didn't allocate memory for a d pointer: struct data *d;. This lines only creates a pointer, it doesn't alloc memory for it. Please try the following code:
int main()
{
struct data *d = (struct data*)malloc(sizeof(struct data));
int *ptr;
int key=10000;
d->b=&key;
ptr=(int *)d->b;
printf("%d\n",*ptr);
free(d);
}