All references to clauses of the ISO standard and to sections of the former ANSI standard will be presented in pairs. For example, subclause 6.4 or §3.4 references constant expressions.
The syntax for initializers (subclause 6.5.7 or §3.5.7) is changed to the following, and the constraints and semantics are augmented by the following:[Footnote 1]
initializer: assignment-expression { initializer-list } { initializer-list , } initializer-list: designation(opt) initializer initializer-list , designation(opt) initializer designation: designator-list = designator-list: designator designator-list designator designator: [ constant-expression ] . identifier
No initializer shall attempt to provide a value for an object not contained within the entity being initialized.[Footnote 2]
If a designator has the form
[ constant-expression ]then the current object (defined below) shall have array type and the expression shall be an integral constant expression that shall evaluate to a valid index for that array. If the array is of unknown size, any nonnegative index value is valid.
If a designator has the form
. identifierthen the current object (defined below) shall have structure or union type and the identifier shall be a member of that type.
Each brace-enclosed initializer list has an associated current object. When no designations are present, subobjects of the current object are initialized in order according to the type of the current object: array elements in increasing subscript order, structure members in declaration order, and the first member of a union.[Footnote 3] In contrast, a designation causes the following initializer to begin initialization of the subobject described by the designator. Initialization continues forward, as normal, after the designated initializer.[Footnote 4] (The designation can be thought of as a ``goto'' within the current object.)
Each designator list begins its description with the current object associated with the closest-surrounding brace pair. Each item in the designator list (in order) specifies a particular member of its current object and changes the current object for the next designator (if any) to be that member.[Footnote 5] The current object that results at the end of the designator list is the subobject to be initialized by the following initializer.
The initialization shall occur in initialization list order, each initializer provided for a particular subobject overriding any previously listed initializer for the same subobject; all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.
If an array of unknown size is initialized, its size is determined by the largest indexed element with an explicit initializer.[Footnote 6]
enum { Mem_One, Mem_Two, /*...*/ }; const char *nm[] = { [Mem_Two] = "Mem Two", [Mem_One] = "Mem One", /*...*/ };Structure members can be initialized to nonzero values without depending on their order:
div_t answer = { .quot = 2, .rem = -1 };Designators can be used to provide explicit initialization when unadorned initializer lists might be misunderstood:
struct { int a[3], b; } w[] = { [0].a = {1}, [1].a[0] = 2 };Space can be ``allocated'' from both ends of an array by using a single designator:
int a[MAX] = { 1, 3, 5, 7, 9, [MAX-5] = 8, 6, 4, 2, 0 };In the above, if
MAX
is greater than ten, there will be some zero-valued
elements in the middle; if it is less than ten, some of the values
provided by the first five initializers will be overridden by the second
five.
Finally, any member of a union can be initialized:
union { /*...*/ } = { .any_member = 42 };____________________________________________________________________
=
punctuator that ends the
designation is unnecessary, strictly speaking. The redundancy
can help an implementation recover from syntactic errors, and also
simplifies any future extensions in this area (such as some form
of repetition).