Static array in struct on heap or stack? - c

Let's say you have a static array as an attribute of a struct
struct example {
char array [5];
};
struct example* exp = (struct example*)malloc(sizeof(struct example));
...initialize and so on...
Now is the static array in the struct considered to be on the heap or stack? In addition is it any more efficient to have an array with specified size in the struct vs a dynamically allocated array, i.e. a pointer that will point to the dynamic memory once you allocate it, attribute in terms of time to allocate? Lastily if it is on the stack does the stack eliminate the variable right when the struct is freed?

You are using the malloc function to allocate a memory.
So, using malloc function to allocate a memory for any variable, or a structure, it will allocate a memory in heap only.
You declaring a variable "a", this is the member of structure. So, in here you are not allocating a memory. You just declare a structure.
After that you allocating a memory using malloc, in here only the memory will be allocated in the heap.

In your code struct example will have size of 5 bytes which contains the character array in there. With the malloc command you have allocated 5 bytes which contains the structure completely. malloc will allocate memory off the heap. The character array array is the first (and only) 5 bytes of the allocated memory.
Given this is a small amount of memory you may just want a stack variable to hold it rather than allocate off the heap. If you are only using it for the duration of the function. In which case you can simply go:
struct example exp;
Now this is just a structure on the stack, so no overhead used in allocating it. Of course if this was a massive structure then it wouldn't be so wise to do it that way.

The array is a part of the structure. Wherever the structure is, the array is inside it.
If you use heap, it is no different from allocating a variable size array. In fact, you can increase the size of the allocation and it'll give you more space for the array. E.g. if you allocate 10 bytes, you will be able to use 10 elements in the array - array[0] to array[9]. And, in reverse, if you allocate only 2 bytes, you still can use the 2 elements of the array - array[0] and array[1]. So the number 5 that you have specified only matters for sizeof().
Of course, if you use it as a local variable in the stack, it is all different.

Related

C struct with dynamic array member place of allocation in memory problem

I am wondering where is foo and arr* being allocated in this sample program. Is foo allocated on stack with constant size or does it change when I use malloc on *arr? If I were to change foo.arr[i] for i from 0 to 4, would it change size of anything? Is foo.arr being allocated on heap? Does change of size of foo.arr change size of foo?
typedef struct {
int size;
int* arr;
} S;
int main(void) {
S foo;
int new_size = 5;
foo.size = new_size;
foo.arr = malloc(new_size * sizeof(int));
free(foo.arr);
return 0;
}
Your confusion stems from conflating the pointer with the allocated space. A pointer is, naively, just a variable that holds a value that describes the address in memory of another value. The space required for the pointer is determined by the maximum addressable space of architecture, not by the allocated block of memory. Think referentially.
In this case, foo is allocated in the stack and the size of the structure instance remains unchanged. malloc is taking care of the mechanics of memory allocation for you and returning a fresh memory address to the allocated space. Subsequently, you are taking that memory address and saving it in the arr member.
Furthermore, anything that is allocated in the stack has to be fixed size in nature. The size of the stack frame needs to be known upon calling the function. Consider the fact that every argument to a procedure has to be of known size or a pointer to some structure allocated in the heap.
Now, all that considered, there exist mechanisms to declare variable sized structures, but you would need to take care of allocating the structure in the heap and handling memory explicitly. The C99 standard introduced flexible array member, which allows placing a size undetermined array within a structure declaration, granted that it is accompanied by another member and it is placed as the last member of the structure.
When you do S foo; you allocate an element of type S in the stack composed of two int, generally 32 bits for an int, so you have allocated 64 bits.
Then you do foo.arr = malloc(new_size * sizeof(int));, you have allocated in the heap a certain amount of contiguous bits, and now foo.arr will point to (->) the first 32 bits.
Additional answers :
If I change foo.arr[i] for i from 0 to 4, would it change size of
anything?
No, since you will only change values in memory not size.
Does change of size of foo.arr change size of foo?
No, from the moment arr is allocate on heap the size of foo will remains the same.

Size of array with malloc function

I am learning C programming and this is my first course in programming. I am having some trouble with this snippet of code:
int* intArray;
intArray=(int*)malloc(5*sizeof(int));
I believe the number of elements in the array is 5 integers. However, what I don't really understand is the malloc function. Does it allocate enough memory for the addresses of 5 integers in this case?
Malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. The parameter is the size, in bytes, to be allocated. So in the line intArray = (int*)malloc(5*sizeof(int)); you are requesting the allocation of memory sufficient for 5 ints (sizeof(int) gives the size of an int type). (malloc)
Using malloc requests the allocation of memory sufficient for 5 new integers.
No, the malloc allocates enough memory for 5 integers. It allocates what is passed into the function: 5*sizeof(int). What might be confusing you is that intArray is a pointer allocated on the stack, which points to the memory address of the beginning of the malloc'ed memory.
If you want memory for addresses of 5 integers, you would do something like:
int** intArray;
intArray=(int**)malloc(5*sizeof(int*));
The malloc function allocates the number of bytes you request in the argument and returns the address in memory of the beginning of the block. In this case you have requested a block of memory large enough to hold 5 integer values.
You cast it to an int * so the compiler will handle the address as containing integers when indexing and dereferencing.
Malloc function call as you observe requires a value specifying number of bytes. From the documentation on malloc:
void* malloc (size_t size);
Allocate memory block. Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
Hence, in your code snippet:
intArray=(int*)malloc(5*sizeof(int));
int size is 2 bytes. sizeof(int) returns 2. Hence 5 * sizeof(int) = 10. So, code resolves to intArray = (int*)malloc(10);

How many calls to free() are needed for `pixel (*copy)[rows] = malloc(cols * sizeof (*copy))`

I have seen various suggestions to allocate 2D arrays in C99 with expressions like this:
int (*array)[cols] = malloc(rows * sizeof *array);
I want to know three things:
Is the entire structure allocated on the heap? Or is this actually a bunch of pointers (on the stack) pointing to arrays on the heap..?
Is the allocated memory completely contiguous?
Is it true that only one call, free(array), is needed to free the whole 2D structure? I read this somewhere - can't remember where - and it seems to work for me, but I'd like to understand why.
(1) Is the entire structure allocated on the heap? Or is this actually a bunch of pointers (on the stack) pointing to arrays on the heap..?
The entire structure (everything that malloc allocates) is on the heap.
(2) Is the allocated memory completely contiguous?
Yes, malloc allocates a contiguous region of storage.
(3) Is it true that only one call, free(array), is needed to free the whole 2D structure? I read this somewhere - can't remember where - and it seems to work for me, but I'd like to understand why.
Yes, it's true. As to the why of it, why would it be any other way? You allocate a single region of storage using malloc, and free is used to de-allocate a single region of storage that was returned by a prior malloc.
I suspect you're confused by the declaration type, though you don't mention it:
int (*array)[cols]
This means that the array variable becomes a single pointer (which is itself allocated on the stack) to an array-of-int with cols elements (which is allocated on the heap due to the use of malloc). Compare this to the more common:
int *array[cols]
... which instead declares a 1-dimensional array of pointers (where the array itself will be on the stack). You might use this latter to create an array-of-pointers-to-arrays, by storing a pointer to a series of arrays in each element (arrays which you would indeed have to allocate and free individually!). This kind of construction can be used in a similar way to a 2D array, but is not really the same thing.
Remember also that a pointer in C can always point at an array. So, even though the first declaration declares a pointer to a 1-dimensional array, it can be used to point at an array of such arrays, i.e. a 2-dimensional array as you wanted. And indeed, the malloc call allocates storage for such an array:
malloc(rows * sizeof *array);
here, sizeof *array is the size in bytes of a (single) 1D array with cols elements. When multiplied by the number of rows, it yields the storage requirement of a 2D array with size rows × cols.
C does not do hidden memory allocation. The type in the question can be used as a true 2D array. Actually it is a "pointer to array[cols] of int".
OTOH, something like int *array[cols] (note the missing parenthesis) is not a 2D array, but an "array of pointers to int". Yet even here you have to malloc the array and each row explicitly!
And for every malloc you need a corresponding free.
Note that the C standard does not require a heap, stack or any other specific management structure. This is left to the implementation. However, most hosted environments (i.e. full-sized run-time) use something like a heap.
Remember to check the result of malloc and handle allocation failure appropriately.

Allocating and reallocating a struct and its elements

I have a few questions about allocating memory to structs and their members.
Suppose I have a struct like this:
struct _MyStruct
{
char *a;
}
typdef struct _MyStruct MyStruct;
I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case? Example:
MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
MyStruct *myStrCopy = myStr;
myStrCopy->a=malloc(sizeof(char));
//checking for null//
Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?
Can I allocate more memory to 'a' than I allocated to myStr?
Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?
I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case?
Well, your MyStruct always needs to exist, but there are several ways to do this and you should go for the simplest one that fits your use case.
Basic approach:
MyStruct myStr;
myStr.a = malloc(N); // "N chars please!"
// You can still get a pointer to this object:
foo(&myStr);
// Don't forget to free the `char` buffer later
free(myStr.a);
Dynamic allocation — valid, but not inherently necessary:
MyStruct* myStr = malloc(sizeof(MyStruct));
myStr->a = malloc(N); // "N chars please!"
// It's already a pointer, so:
foo(myStr);
// Don't forget to free the `char` buffer later
free(myStr->a);
// And then the struct
free(myStr);
Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?
It's a new block.
Each block of dynamically allocated memory is entirely separate. When you made the member variable a a pointer, you ensured that although a lives within the struct, the thing it points to does not (unless you make it point to itself, lol).
myStr (or *myStr): your malloc'd memory:
0 32 0 8 16 24 32 40 ...
+----------+ +------------------------------+
| char* a——|———————————————————————→| text or whatever here |
+----------+ +------------------------------+
(somewhere in memory) (somewhere else in memory)
The above diagram is valid no matter which way you constructed myStr.
Can I allocate more memory to 'a' than I allocated to myStr?
Yeah, whatever you want. It's separate. You have indirection.
Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?
No.
Just for clarification:
myStr and
a are just pointer to some memory location. This does not mean they are sharing the same memory location.
So allocating either myStr or a is not growing the variable it self.
It requests new memory somewhere in the virtual memory space of the process and stores the address in the corresponding pointer..
So to answer you question: Yes you can allocate a memory for a which is larger than myStr.
Update for better illustration:
0x000 | 0x004 | 0x008 | 0x0012 | 0x0016
^ ^
| |
myStr a
So myStr could be located in memory somewhere completly different compared to a.
Not needed to allocate for structure.Just for char* is enough. Say
MyStruct str;
str.a = malloc( sizeof(char)*10);
str will be in stack. Memory pointed by 'a' will be in heap. So when str goes out of scope, the object will be destructed. But not the dynamically allocated one which is pointed by 'a'. We have delete it manually.
The size of structure will be same won't vary with the size of dynamic memory pointed by 'a'.
Just reallocate the memory pointed by 'a'.
str.a = realloc(a, sizeof(char)*20);
First case
MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
yes, very much. Without the allocation to myStr first, trying to dereference myStr (to reach a) is undefined behaviour.. Also, FWIW,
myStrCopy->a=malloc(sizeof(char));
allocates only memory for only one char, be sure that is what you actually want. If you really want that, in that case, you can rewrite that as
myStrCopy->a=malloc(1);
as sizeof(char) is guranteed to be 1 in C.
Every allocation through malloc() and family gives you a new memory, if successful.
You can, and you should. There is no relation actually. They are separate variables and need seperate memory allocation.
No, only realloc() on a should suffice.

Finding the size of the structure dynamically

Is there any way to find the structure size dynamically in C??
Sizeof is compile time operator.. so what's the other option.
If we can have dynamically allocated array(flexible arrays) in a structure, then finding the structure size dynamically should also be there.. Plz help me out...
When you allocate an array dynamically in C, then you must remember its size too, if you wish to know the size of the array!
Structure sizes must be known at compile-time.
If it contains a pointer to dynamically allocated memory then that memory is not part of the struct - it's outside the struct and the pointer is pointing at it - so it does not affect the sizeof the struct.
If you're talking about flexible array member then you will need to implement your own way of knowing how much memory you allocated, e.g. have a struct member variable that holds the size.
sizeof's results are compile time constant as a the size of a variable or structure does not change during run-time.
The only exception to this are V(ariable)L(ength)Arrays for which the code defnding them "knows" the size.
Referring:
we can have dynamically allocated array in a structure
So let's assume:
struct s
{
size_t size;
int * ints;
}
The size is sizeof(struct s). That is the sum of
the size of an unsigned interger: sizeof(size_t)
the size of a pointer to int: sizeof (int *)
some optional padding bytes
This is independed of to how many bytes the structure's member int * ints may point.

Resources