The way the buf
member is declared is taking advantage of a C99 feature called flexible arrays, the main advantage is to gain the use of variable length array like features inside a struct. Since buf
is declared without a size it occupies no space until you explicitly allocate it when dynamically allocating a struct sdshdr *.
It is more efficient than using a char * since if buf
was a char * we would have to perform two dynamic allocations, first for a struct sdshdr * and then again for buf
and the pointer itself would require additional space. This is cleaner since the allocation either succeeds or fails as a unit and cleaning up is simpler since only one free
is required. We also gain locality of data since the whole structure is allocated in a block and does not require a separate dereference to access buf
.
The draft C99 standard in section 6.7.2.1
has a nice example that shows how to use this feature:
EXAMPLE After the declaration:
struct s { int n; double d[]; };
the structure struct s has a flexible array member d. A typical way to use this
is:
int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
and assuming that the call to malloc succeeds, the object pointed to by p
behaves, for most purposes, as if p had been declared as:
struct { int n; double d[m]; } *p;
(there are circumstances in which this equivalence is broken; in particular, the
offsets of member d might not be the same).