Oxdeadbeef
Oxdeadbeef

Reputation: 1063

One element array in struct

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

Answers (2)

Chris Lutz
Chris Lutz

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

Will Robinson
Will Robinson

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

Related Questions