Arrays of Length Zero
=====================
Zero-length arrays are allowed in GNU C. They are very useful as the
last element of a structure which is really a header for a
variable-length object:
struct line {
int length;
char contents[0];
};
struct line *thisline = (struct line *)
malloc (sizeof (struct line) + this_length);
thisline->length = this_length;
In ISO C89, you would have to give `contents' a length of 1, which
means either you waste space or complicate the argument to `malloc'.
In ISO C99, you would use a "flexible array member", which is
slightly different in syntax and semantics:
* Flexible array members are written as `contents[]' without the `0'.
* Flexible array members have incomplete type, and so the `sizeof'
operator may not be applied. As a quirk of the original
implementation of zero-length arrays, `sizeof' evaluates to zero.
* Flexible array members may only appear as the last member of a
`struct' that is otherwise non-empty. GCC currently allows
zero-length arrays anywhere. You may encounter problems, however,
defining structures containing only a zero-length array. Such
usage is deprecated, and we recommend using zero-length arrays
only in places in which flexible array members would be allowed.
GCC versions before 3.0 allowed zero-length arrays to be statically
initialized. In addition to those cases that were useful, it also
allowed initializations in situations that would corrupt later data.
Non-empty initialization of zero-length arrays is now deprecated.
Instead GCC allows static initialization of flexible array members.
This is equivalent to defining a new structure containing the original
structure followed by an array of sufficient size to contain the data.
I.e. in the following, `f1' is constructed as if it were declared like
`f2'.
struct f1 {
int x; int y[];
} f1 = { 1, { 2, 3, 4 } };
struct f2 {
struct f1 f1; int data[3];
} f2 = { { 1 }, { 2, 3, 4 } };
The convenience of this extension is that `f1' has the desired type,
eliminating the need to consistently refer to `f2.f1'.
This has symmetry with normal static arrays, in that an array of
unknown size is also written with `[]'.
Of course, this extension only makes sense if the extra data comes at
the end of a top-level object, as otherwise we would be overwriting
data at subsequent offsets. To avoid undue complication and confusion
with initialization of deeply nested arrays, we simply disallow any
non-empty initialization except when the structure is the top-level
object. For example:
struct foo { int x; int y[]; };
struct bar { struct foo z; };
struct foo a = { 1, { 2, 3, 4 } }; // Valid.
struct bar b = { { 1, { 2, 3, 4 } } }; // Invalid.
struct bar c = { { 1, { } } }; // Valid.
struct foo d[1] = { { 1 { 2, 3, 4 } } }; // Invalid.