How to initialize structures to all-elements-zero-or-null

(This page is here because this is a question which seems to come up
reasonably frequently, and it's useful to have the answer all written down
in one place to refer to.)

When you declare a structure in `static storage' (meaning with the keyword
static or at file scope), it is initialised with all numeric
members zero and all pointers null. How should one achieve the same thing
when initialising a structure in automatic or dynamic storage? Let's assume
that this structure is defined by somebody else (say, POSIX), and in the
normal fashion of such standards, all you know about the structure is that it
contains at a minimum a certain set of elements; you do not know its
exact contents.

Unfortunately, neither achieves the intended effect. There is no guarantee
that the machine representation of zero is all-bits-zero, nor that the
representation of a null pointer is all-bits-zero. (Note that the fact that you
can initialise a null pointer by setting it to `0' doesn't signify
here: the standard defines a `null pointer constant' as 0 or
(void*)0, but makes no statement about its in-memory
representation. It is not even guaranteed that different types of pointer have
the same representation.)

The correct answer is to say

struct bar baz = {0};

or, for dynamic storage, something like

struct bar *baz, zz = {0};
baz = malloc(sizeof *baz);
*baz = zz;

-- note the ugly declaration of zz. You can do slightly better
with a macro such as

-- but since the whole point of this exercise is to make the code portable,
that's kind of pointless. As an alternative, you could declare a static
`zeroed' instance of struct foo in the same header as the
structure is defined, and then assign that to things later. None of these
has the virtue of being elegant or pretty.

(It's also worth noting that if you use = {0} to initialise
a structure which contains other aggregate types, current versions of GCC will
issue a warning such as,

-- this is irritating, but there's not much that can be done about it.)

Justification

The typical objections to this approach are `You don't know what's in the
structure, so you don't know whether the first element can be initialised to
0'; or, `What happens to the elements of the structure after the
first?' Both are wrong. The basic game here is that:

You don't have to initialise every element of a structure, but can
initialise only the first one; you don't need nested {} even
to initialise aggregate members of a structure.

Anything in C can be initialised with = 0; this
initialises numeric elements to zero and pointers null.

From the Standard (actually from the final draft, but I don't think these
have changed since then),

[6.7.8.20] If the aggregate contains elements or members that are aggregates or
unions, or if the first member of a union is an aggregate or union, these rules
apply recursively to the subaggregates or contained unions. If the initializer
of a subaggregate or contained union begins with a left brace, the
initializers enclosed by that brace and its matching right brace initialize the
elements or members of the subaggregate or the first member of the contained
union. Otherwise, only enough initializers from the list are taken to account
for the elements or members of the subaggregate or the first member of the
contained union; any remaining initializers are left to initialize the next
element or member of the aggregate of which the current subaggregate or
contained union is a part.

[6.7.8.21] If there are fewer initializers in a brace-enclosed list than there
are elements or members of an aggregate, or fewer characters in a string
literal used to initialize an array of known size than there are elements in
the array, the remainder of the aggregate shall be initialized implicitly the
same as objects that have static storage duration.

so struct foo bar = {0} always initialises the first element of
the first subelement of bar as if it had been initialised with
= 0 and initialises the rest `[in] the same [way] as objects that
have static storage duration'.

It would be neater to be able to say struct foo bar = {}, and
some compilers (e.g. GCC) permit this, but the ANSI grammar requires an
initialiser list to be non-empty.

Who cares?

Arguably, only pedants like me. The portability argument is on the face of
it quite a strong one, but actually I think it's a bit of a sham. After all,
there's so much bad C code out there which just calls memset
that you'd be mad to build a new processor or MMU which didn't use
all-bits-zero as the representation of a zero numeric value or as an invalid
pointer which can be used as a null pointer.