I'm writing array list in C.
I defined an implementation specific struct against a general header.
struct array_list_env {
void **array; // pointer to the array
size_t capacity; // length of the array
size_t size; // number of occupied elements in the array
}
Now when I try to change the void **array
into void *array[]
I got,
error: flexible array member not at end of struct
What is a flexible array member?
A flexible array member is an array without a specified size. The member has to be the last member of the struct. The actual array size is set when you allocate memory for the struct. Consequently, it only makes sense together with dynamic allocation.
Example:
#define ARRSIZE 10
struct FAM
{
size_t sz;
int arr[]; // Must be last struct member
};
struct FAM* fam = malloc(sizeof(struct FAM) + ARRSIZE * sizeof(int));
Now fam->arr
is an array with ARRSIZE
elements that you can access ussing fam->arr[index]
.
Further code like:
struct FAM* famA = malloc(sizeof(struct FAM) + 10 * sizeof(int));
struct FAM* famB = malloc(sizeof(struct FAM) + 1000 * sizeof(int));
will give you two pointers of the same type even though the size of the arrays differ.
So why would I use it?
Look at this code
struct FAM
{
size_t sz;
int arr[];
};
struct P
{
size_t sz;
int* p;
};
int getFAM(struct FAM* f, unsigned long x)
{
return f->arr[x];
}
int getP(struct P* p, unsigned long x)
{
return p->p[x];
}
It's two ways of doing "the same". One using a flexible array member, the other using a pointer.
Compiled with gcc -O2 on https://godbolt.org/ I get
which indicates that the flexible array can save you one indirection and thereby generate faster code.
It can be described like: In case of a flexible array member the array has fixed offset from a struct pointer while in case of a pointer-to-int member the array is located where the pointer value says. Consequently, in the first case the compiler can use that "known fixed offset" directly but in the second case the compiler must read the pointer value first and then read the array data.
Note: This example is for one specific system (aka compiler/cpu type). On other systems the result may differ.