|
P99
|
Collaboration diagram for Flexible array members:Defines | |
| #define | calloc(...) P99_CALL_DEFARG(calloc, 2, __VA_ARGS__) |
| Default arguments for C99 function calloc. | |
C99 allows to define a flexible array member as the last member of a struct, namely an array of undetermined length.
P99_DECLARE_STRUCT(package_head); struct package_head { char name[20]; size_t len; uint64_t data[]; };
Such a struct can then allocated on the heap with a suitable size such that the field data has as much elements as fit in the allocated space from the start of data onward. Usually one would allocate such struct with
package_head *a = malloc(sizeof(package_head) + 10 * sizeof(uint64_t)); package_head *b = malloc(sizeof(*b) + 12 * sizeof(b->data[0]));
This has several disadvantages. First the syntax is clumsy, we have to use a relatively complicated expression that uses two elements of the specification of a or b.
Then this is wasting space. Due to packing of the struct the offset of data "inside" the struct may be less than sizeof(package_head). In most cases the real size of the object that we want to construct is
offsetof(package_head, data) + N * sizeof(uint64_t)
so we are wasting
sizeof(package_head) - offsetof(package_head, data)
bytes.
The above formula for the exact size is only valid for larger values of N. We must also ensure that we allocate at least sizeof(package_head) bytes. So the complete formula for looks something like
#define P99_FSIZEOF(T, F, N) P99_MAXOF(sizeof(T), offsetof(T, F) + P99_SIZEOF(T, F[0]) * N)
which is probably not something that you want to write on a daily base.
We provide several interfaces to allocate struct with flexible members
1.7.6.1