Reputation: 22695
struct Register
with each register having a dynamically allocated array of struct Field
?Register_A.FieldArray[23].High
?)?How will I initialize register structure efficiently(assuming that register struct array is a big one) ? (Like a data segment without spending any compute)
struct Field
{
char High;
char Low;
char Attribute;
};
struct Register
{
unsigned int ResetValue;
struct Field FieldArray[];
};
Upvotes: 2
Views: 1999
Reputation: 56069
I strongly discourage you from using a flex array, because they're nothing but a kludge. You should instead declare and use it as a struct Field *
, malloc
ing it to size like any other dynamic array.
That said, to malloc
with an array size of n_elem
:
struct Register register = malloc(sizeof(*register) + n_elem * sizeof(*register->FieldArray));
To access the elements:
char high = register->FieldArray[0].High;
For initialization: in gcc, at least, you can initialize the array part statically like any other static array. I'm not sure how other compilers handle it.
Why flex arrays are discouraged:
I'll link this post, but I don't think the answer is complete (most of the discouragement is because it's c-99 only), so I'll add my thoughts.
They are an exception. In essence, you're declaring the array to be of zero size and accessing it out of bounds every time, just to an extent you have allocated for. You can't use a struct with a flexible array just like any other struct, e.g. you can't take the sizeof
the flexible array. If you declare a static one or an array of them, you can't use the array member because there's no space allocated for it.
Example of using them in an array:
#include <stdio.h>
struct test {
int val;
int arr[];
};
int main() {
struct test tarr[2];
printf("%p\n%p\n", &tarr[0].arr[0], &tarr[1].val);
}
Output:
0x7fff59b67164
0x7fff59b67164
They are at the same address. If you try to write to the array member, you overwrite the next object. If you try to read from it, you read data from the next object. Depending on padding, this could even be a nonsense value from the padding.
They're like goto
statements, both are potentially useful but more often a bad idea. If you don't know why they're dangerous, you shouldn't be using them (in real code; it's not a bad idea to play around with them in a test program to see how to use them correctly and how they can introduce problems).
Upvotes: 3
Reputation: 78923
Flexible array members are a part of C99.
struc
with flexible array member just as you think you should: malloc(sizeof(struct Register) + sizeof(struct Field[n]))
, where n
is the size you want. Don't forget to initialize the array and to keep track of n
, best by dedicating a member to that purposeBTW: the malloc
above may be wasting some bytes due to padding, but usually it is not worth thinking about the exact formula. The minimal one has a max and uses offsetof
.
Upvotes: 0
Reputation:
A way to do it is by changing the size of the struct Register
:
struct Register
{
unsigned int ResetValue;
struct Field FieldArray[1];
};
struct Register *Register_Create()
{
struct Register *reg = calloc(1, sizeof(struct Register) - sizeof(struct Field));
// check for NULL pointer
return reg;
}
struct Register *Register_SetSize(struct Register *reg, size_t size)
{
// check for NULL
reg = realloc(reg, sizeof(struct Register) + sizeof(struct Field) * (size - 1));
// check for NULL
return reg;
}
Here's an example on how to use this:
struct Register *reg = Register_Create();
reg = Register_SetSize(register, 5);
// You now have space for 5 elements in reg->FieldArray
reg->FieldArray[3].High = 'B';
Keep in mind that this solution only works if FieldArray
is placed at the end of the struct
.
Upvotes: 1
Reputation: 11896
You are going to have to know how big the FieldArray is. If it isn't fixed, you need to declare with max value. Then you can just alloc a Register and access as you specified
Upvotes: 0