gcc: Zero Length
1
1 6.17 Arrays of Length Zero
1 ==========================
1
1 Zero-length arrays are allowed in GNU C. They are very useful as the
1 last element of a structure that is really a header for a
1 variable-length object:
1
1 struct line {
1 int length;
1 char contents[0];
1 };
1
1 struct line *thisline = (struct line *)
1 malloc (sizeof (struct line) + this_length);
1 thisline->length = this_length;
1
1 In ISO C90, you would have to give 'contents' a length of 1, which
1 means either you waste space or complicate the argument to 'malloc'.
1
1 In ISO C99, you would use a "flexible array member", which is slightly
1 different in syntax and semantics:
1
1 * Flexible array members are written as 'contents[]' without the '0'.
1
1 * Flexible array members have incomplete type, and so the 'sizeof'
1 operator may not be applied. As a quirk of the original
1 implementation of zero-length arrays, 'sizeof' evaluates to zero.
1
1 * Flexible array members may only appear as the last member of a
1 'struct' that is otherwise non-empty.
1
1 * A structure containing a flexible array member, or a union
1 containing such a structure (possibly recursively), may not be a
1 member of a structure or an element of an array. (However, these
1 uses are permitted by GCC as extensions.)
1
1 Non-empty initialization of zero-length arrays is treated like any case
1 where there are more initializer elements than the array holds, in that
1 a suitable warning about "excess elements in array" is given, and the
1 excess elements (all of them, in this case) are ignored.
1
1 GCC allows static initialization of flexible array members. This is
1 equivalent to defining a new structure containing the original structure
1 followed by an array of sufficient size to contain the data. E.g. in
1 the following, 'f1' is constructed as if it were declared like 'f2'.
1
1 struct f1 {
1 int x; int y[];
1 } f1 = { 1, { 2, 3, 4 } };
1
1 struct f2 {
1 struct f1 f1; int data[3];
1 } f2 = { { 1 }, { 2, 3, 4 } };
1
1 The convenience of this extension is that 'f1' has the desired type,
1 eliminating the need to consistently refer to 'f2.f1'.
1
1 This has symmetry with normal static arrays, in that an array of
1 unknown size is also written with '[]'.
1
1 Of course, this extension only makes sense if the extra data comes at
1 the end of a top-level object, as otherwise we would be overwriting data
1 at subsequent offsets. To avoid undue complication and confusion with
1 initialization of deeply nested arrays, we simply disallow any non-empty
1 initialization except when the structure is the top-level object. For
1 example:
1
1 struct foo { int x; int y[]; };
1 struct bar { struct foo z; };
1
1 struct foo a = { 1, { 2, 3, 4 } }; // Valid.
1 struct bar b = { { 1, { 2, 3, 4 } } }; // Invalid.
1 struct bar c = { { 1, { } } }; // Valid.
1 struct foo d[1] = { { 1, { 2, 3, 4 } } }; // Invalid.
1