Finding the size of the structure dynamically - c

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.

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.

Static array in struct on heap or stack?

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.

C struct pointer

I was trying to understand some code written by others. But I am not very familiar with C. Could anyone explain the following code? Thx ahead!
struct cell *ptr = (struct cell* ) malloc ( (input * 1024) * sizeof(struct cell));
This code creates a pointer of type struct cell named ptr which points to a memory location- a sequence of (input*1024) number of blocks, where each block is of size sizeof(struct cell)
This is dynamic memory allocation. During runtime if there is not that much amount of free memory, it will return NULL and ptr will be pointing to NULL It always advised to check ptr for NULL value before playing with it.
As you have allocated the memory dynamically, it's your responsibility to free/reclaim it by calling free(ptr) once you are done.
This was a way of allocating memory in the 1970s which is still sometimes seen today, perhaps due to a "cargo cult" programming mentality.
The effect is to allocate a contiguous array which has 1024 * input number of elements, and each element is an (uninitialized) struct cell.
Today we would write:
struct cell *ptr = malloc( input * 1024 * sizeof *ptr );
or
struct cell *ptr = calloc( input * 1024, sizeof *ptr );
The latter will also initialize any integers in the struct to have value 0, and any char arrays to contain empty strings; and may be faster depending on the operating system.
The sizeof *ptr part is necessary because the malloc family of functions expect number of bytes instead of number of elements so we must multiply by the number of bytes per element; and if ptr points to an element, then *ptr is an element, so sizeof *ptr retrieves the size of that element.
For explanation of why the old style is no longer in favour, see here.
This code dynamically allocates a number of struct cell's. The number is equal to input*1024. As a result ptr will be a 1D array of structs. Don't forget to free() it!
Also say to these others not to cast malloc().
The function malloc is used to dynamically allocate memory, it is used when you have no prior knowledge of how large something will be beforehand. Its argument is the number of bytes you want. Given an input, in this case input, it will give you that number of struct cells times 1024. Think of it like a matrix, where 1024 is the width and input is the height. Finally the function returns the pointer to the allocated memory block which is stored in ptr so that you can use it.In a object oriented language it is the equivalent of creating an array of objects, the size of the "object" is the size of the cell, input would be the number of such "arrays of objects" you are creating, and 1024 is the array length.

Getting array size in C. Cannot understand output

I am curious why I am getting the following behaviour in my code.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int M=24;
int arr[M];
int N=24;
int* ptr=(int*) malloc(sizeof(int)*N); /*Allocate memory of size N */
printf("Size of your malloced array is %lu\n",sizeof(ptr)/sizeof(ptr[0])); /* Get the size of memory alloctaed. Should be the same as N?*/
printf ("Size of your normal arrays is %lu\n",sizeof(arr)/sizeof(arr[0])); /* Ditto */
free(ptr);
return 0;
}
The output is
Size of your malloced array is 2
Size of your normal arrays is 24
I would have thought the output would be 24 in both places. How then does one get the size of the malloced array If somehow I have "forgotten" it?
Surely the pointer ptr will contain some information about the size of the malloced array since when we call free(ptr) it will release the array just malloced
When you use sizeof() on a pointer, you get the size of the pointer. Not the size of the allocated array. In your case, a pointer is probably 8 bytes and an int is 4 bytes, hence why you get 2.
In short, you can't get the size of an allocated array. You need to keep track of it yourself.
EDIT : Note that some compilers do actually support this functionality as an extension:
For example, MSVC supports _msize(): http://msdn.microsoft.com/en-us/library/z2s077bc.aspx
While sizeof() works as you'd expect with fixed-length and variable-length arrays, it doesn't know anything about the sizes of malloc()'ed arrays.
When applied to a pointer, sizeof() simply returns the size of the pointer.
More generally, given a pointer to a malloc()'ed block, there's no standard way to discover the size of that block.
See C FAQ questions 7.27 and 7.28.
In summary, if you need to know the size of a heap-allocated array in a portable manner, you have to keep track of that size yourself.
You cannot obtain, at runtime, the size of an array if you only have a pointer to (the first element of) the array. There are no constructs at all in C that allow you to do this. You have to keep track of the length yourself.
If you happen to have an array rather than a pointer then you can find its length, but not for a pointer to an element of the array.
In your code, ptr is a pointer and so you cannot find out the length of the array to which it points. On the other hand, arr is an array and so you can find out its length with sizeof(arr)/sizeof(arr[0]).
As this other question points out, there is no portable way getting the size of a dynamic array, since malloc may allocate more memory than requested. Furthermore managing malloc requests is up to the operating system. For instance *nix would calls sbrkand store the requests somewhere. So, when you call sizeof(ptr) it returns the size of the pointer and not the size of the array. On the other hand, if your array is fixed, the size of it is determined at compile time, so the compiler is able to replace sizeof(arr) with the size of the fixed array, thus providing you the "correct" size.
The size of a pointer is 4 bytes on 32-bit machines and 8 bytes on 64-bit machines. I guess you work on a 64-bit machine since the size of an int is 4, and you got that sizeof(ptr)/sizeof(ptr[0]) is 2.
The thing to remember about sizeof is that it is a compile-time operator1; it returns the number of bytes based on the type of the operand.
The type of arr is int [24], so sizeof arr will evaluate to the number of bytes required to store 24 int values. The type of ptr is int *, so sizeof ptr will evaluate to the number of bytes required to store a single int * value. Since this happens at compile time, there's no way for sizeof to know what block of memory ptr is pointing to or how large it is.
In general, you cannot determine how large a chunk of memory a pointer points to based on the pointer value itself; that information must be tracked separately.
Stylistic nit: a preferred way to write the malloc call is
int *ptr = malloc(sizeof *ptr * N);
In C, you do not need to cast the result of malloc to the target pointer type2, and doing so can potentially mask a useful diagnostic if you forget to include stdlib.h or otherwise don't have a prototype for malloc in scope.
Secondly, notice that I pass the expression *ptr as the operand to sizeof rather than (int). This minimizes bugs in the event you change the type of ptr but forget to change the type in the corresponding malloc call. This works because sizeof doesn't attempt to evaluate the operand (meaning it doesn't attempt to dereference ptr); it only computes its type.
1 The exception to this rule occurs when sizeof is applied to a variable-length array; since the size of the array isn't determined until runtime, a sizeof operator applied to a VLA will be evaluated at runtime.
2 Note that this is not the case in C++; a cast is required, but if you're writing C++ you should be using new and delete instead of malloc and free anyway. Also, this is only true since C89; older versions of C had malloc return char * instead of void *, so for those versions the cast was required. Unless you are working on a very old implementation (such as an old VAX mini running an ancient version of VMS), this shouldn't be an issue.

Initialization of Array inside a Structure in C

I'm trying to allow a variable length array inside a struct in a C program. Something like this:
struct result{
int column;
int row;
const char* a[var][var];
};
how do i do this?
even the following definition would do:
struct result{
int column;
int row;
const char* a[row][column];
};
plese do help...
You can't have variable size arrays in C structs.
You can have pointers to arrays which can be variable size (you need to handle the allocation of the space separately), but you are declaring arrays of pointers instead
If you want an array of pointers, try
const char (*a)[][];
(you'll need to manage the array as an array of pointers to arrays if you want both dimensions to be variable)
Just use pointers instead. You'll have to do dynamic memory allocation. Don't forget to free() the memory allocated for your array :)
P.S.: If you need a 2-dimensional array, use a pointer-to-pointer (that is, allocate memory for an array of pointers)
For single-dimension arrays you can do something like this:
struct TEST {
...
int size;
char string[];
}
where the size field indicates how many characters there are in the string array. The array has to be the last member of the struct, and you have to allocate the struct's memory dynamically. The allocated size should be sizeof(struct TEST) + size * sizeof(char) in this case.
You cannot have more than one variable size array in the struct. Multi-dimension variable-size arrays are trickier. It cannot be done unless only one dimension size is unknown, specifically that of the first dimension.
struct TEST {
...
int size;
char string[][100];
}
EDIT:
As other posters mentioned, you can have pointers to one or more arrays, at the cost of having to manage their memory areas separately from the struct.
EDIT 2:
This is part of at least the ISO C99 standard. Shamelessly copying from paragraph 6.7.2.1, sub-paragraph 16:
16 As a special case, the last element
of a structure with more than one
named member may have an incomplete
array type; this is called a flexible
array member. With two exceptions,
the flexible array member is ignored.
First, the size of the structure shall
be equal to the offset of the last
element of an otherwise identical
structure that replaces the flexible
array member with an array of
unspecified length.106)...
Use dynamic allocation with the malloc function.
In your case you should do something like:
#include <stdlib.h> /* header file for the malloc function */
void allocateResult(struct result* res, int row, int column) {
res->a = (const char*) malloc(row * column * sizeof(char));
}
Please note that sizeof(char) equals to 1 (almost all the time), but for other types you'd have to do it this way.
This solution implies to free allocated memory before the program ends. You'll have to pass the pointer in your struct to free:
void freeResult(struct result* res) {
free(res->a);
}

Resources