the general usage of flexible array is to use malloc to define the flexible array. I'm trying to explore defining the flexible array with another struct. An example
typedef struct {
uint64_t header;
size_t data_size;
float data[];
} test_base_t;
typedef struct {
test_base_t base;
float data[3];
} test_t;
As I understand, flexible array needs to be defined at the end of a struct. And clangd will give the following warning. -Wgnu-variable-sized-type-not-at-end
I just wanted to ask if anybody has done this before and is it safe? Or is there a better way to define flexible array size without alloc?
You can then wrap the usage of the object in a macro to static assert ext.base.data == ext.data
before casting and passing to a general API consumes test_base_t
. This way you can have the memory required in compile instead of allocing.
Edit
There seem to be a confusion on how I wanted to consume it, here is an example to demonstrate
#define SUM_BASE(test) \
sum_base(&test->base); \
_Static_assert(test->data == test->base.data);
float sum_base(test_base_t *base)
{
float sum = 0;
for (size_t i = 0; i < base->data_size; i++)
{
sum += base->data[i];
}
return sum;
}
test_t test = { .base = { .data_size = 3, }, .data = { 1, 2, 3, }, };
SUM_BASE((&test));
You cannot create actual instances of
test_base_t
with an initialized array, but you can create compound literals with an initialized array of a specified length and cast their address astest_base_t
pointers. The layout and alignment of both structures should be compatible, given that they have exactly the same types, save for the flexible array length.Here is an example:
Here is another approach, perhaps closer to your expectations, using a
union
with abase
member with the flexible type and a parametric instance type with the appropriate array size: