Consider a struct containing a flexible array member like the following:
typedef struct {
size_t len;
char data[];
} Foo;
I have an unknown number of Foos, each of which is an unknown size, however I can be certain that all of my Foos together will total exactly 1024 bytes. How can I allocate 1024 bytes for an array of Foos before knowing the length of each Foo, and then fill in the members of the array later?
Something like this, although it throws a segfault:
Foo *array = malloc(1024);
int array_size = 0;
Foo foo1;
strcpy(foo1.data, "bar");
array[0] = foo1;
array_size++;
Foo foo2;
strcpy(foo2.data, "bar");
array[1] = foo2;
array_size++;
for (int i = 0; i < array_size; i++)
puts(array[i].data);
The reason for wanting to do this is to keep all the Foos in a contiguous memory region, for CPU cache friendliness.
You can't have an array of foos, at all, because foo does not have a fixed size, and the defining characteristic of an array is that each object has fixed size and offset from the base computable from its index. For what you want to work, indexing array[n]
would have to know the full size of foo[0]
, foo[1]
, ..., foo[n-1]
, which is impossible, because the language has no knowledge of those sizes; in practice, the flexible array member is just excluded from the size, so foo[1]
will "overlap" with foo[0]
's data.
If you need to be able to access these objects as an array, you need to give up on putting a flexible array member in each one. Instead you could put all the data at the end, and store a pointer or offset to the data in each one. If you don't need to be able to access them as an array, you could instead build a sort of linked list in the allocated memory, storing an offset to the next entry as a member of each entry. (See for example how struct dirent
works with getdents
on most Unices.)