I see this in code sometimes:
struct S
{
int count; // length of array in data
int data[1];
};
Where the storage for S is allocated bigger than sizeof(S) so that data can have more space for its array. It is then used like:
S *s;
// allocation
s->data[3] = 1337;
My question is, why is data not a pointer? Why the length-1 array?
If you declare
dataas a pointer, you’ll have to allocate a separate memory block for thedataarray, i.e. you’ll have to make two allocations instead of one. While there won’t be much difference in the actual functionality, it still might have some negative performance impact. It might increase memory fragmentation. It might result in struct memory being allocated “far away” from thedataarray memory, resulting in the poor cache behavior of the data structure. If you use your own memory management routines, like pooled allocators, you’ll have to set up two allocators: one for the struct and one for the array.By using the above technique (known as “struct hack”) you allocate memory for the entire struct (including
dataarray) in one block, with one call tomalloc(or to your own allocator). This is what it is used for. Among other things it ensures that struct memory is located as close to the array memory as possible (i.e. it is just one continuous block), so the cache behavior of the data structure is optimal.