Reputation: 1063
Why some struct uses a single element array, such as follows:
typedef struct Bitmapset
{
int nwords;
uint32 words[1];
} Bitmapset;
To make it convenient for latter dynamic allocation?
Upvotes: 13
Views: 8245
Reputation: 75429
In a word, yes.
Basically, the C99 way to do it is with an flexible array member:
uint32 words[];
Some pre-C99 compilers let you get away with:
uint32 words[0];
But the way to guarantee it to work across all compilers is:
uint32 words[1];
And then, no matter how it's declared, you can allocate the object with:
Bitmapset *allocate(int n)
{
Bitmapset *p = malloc(offsetof(Bitmapset, words) + n * sizeof(p->words[0]));
p->nwords = n;
return p;
}
Though for best results you should use size_t
instead of int
.
Upvotes: 18
Reputation: 2299
This is usually to allow idiomatic access to variable-sized struct instances. Considering your example, at runtime, you may have a Bitmapset that is laid out in memory like this:
-----------------
| nwords | 3 |
| words[0] | 10 |
| words[1] | 20 |
| words[2] | 30 |
-----------------
So you end up with a runtime-variable number of uint32 "hanging off" the end of your struct, but accessible as if they're defined inline in the struct. This is basically (ab)using the fact that C does no runtime array-bounds checking to allow you to write code like:
for (int i = 0; i < myset.nwords; i++) {
printf("%d\n", myset.words[i]);
}
Upvotes: 8