Reputation: 1197
How do the two implementations differ:
struct queue {
int a;
int b;
q_info *array;
};
and
struct queue {
int a;
int b;
q_info array[0];
};
Upvotes: 4
Views: 2124
Reputation: 7138
q_info array[0];
decays to a pointer because of the automatic conversion. However, it is not assignable. You cannot say
array = <some address of an object>;
afterwards.
Upvotes: 1
Reputation: 25599
These are completely different things:
The reason people do this is it's more space-efficient. You simply over-allocate the memory the struct needs, and then pretend the array has more elements then declared - the compiler won't mind (usually).
It also means you have one less pointer to dereference through, and you can allocate and free the memory for the struct and the array all in one.
Obviously, this trick only works when the array is the last element in the struct.
Upvotes: 2
Reputation: 409482
For the zero-sized array member, you can, when you allocate the structure, allocate more memory than the size of struct queue
(for example malloc(sizeof(struct queue) + sizeof(q_info) * 10)
) to have a contiguous area of memory you can use. Then the array will be part of that memory allocated, and for the example allocation you have ten q_info
entries in it.
For the pointer, you have to make two allocations, one for the queue
structure, and one for the array
member. You of course have to call free
twice, once for the array
pointer and once for the structure.
However, once allocated both can be used the same.
Upvotes: 1
Reputation: 727137
The second struct
does not use an array of zero elements - this is a pre-C99 trick for making flexible array members. The difference is that in the first snippet you need two malloc
s - one for the struct
, and one for the array
, while in the second one you can do both in a single malloc
:
size_t num_entries = 100;
struct queue *myQueue = malloc(sizeof(struct queue)+sizeof(q_info)*num_entries);
instead of
size_t num_entries = 100;
struct queue *myQueue = malloc(sizeof(struct queue));
myQueue->array = malloc(sizeof(q_info)*num_entries);
This lets you save on the number of deallocations, provides better locality of references, and also saves the space for one pointer.
Starting with C99 you can drop zero from the declaration of the array member:
struct queue {
int a;
int b;
q_info array[];
};
Upvotes: 11
Reputation: 14781
In the first one there is actually a pointer allocated in struct queue
, and sizeof(struct queue) == 2 * sizeof(int) + sizeof(q_info*)
In the second one there is no pointer or anything named array
really exists in struct queue
, and sizeof(struct queue) == 2 * sizeof(int)
. This is known as a trick to conveniently reference the data before or later using array
. I've used this trick in implementing a memory allocator.
Upvotes: 1