When initializing an object of struct or union type, the initializer must be a non-empty, (until C23) brace-enclosed, comma-separated list of initializers for the members:
= { expression , ... } | (1) | |
= { designator expression , ... } | (2) | (since C99) |
= { } | (3) | (since C23) |
where the designator is a sequence (whitespace-separated or adjacent) of individual member designators of the form .
member and array designators of the form [
index ]
.
All members that are not initialized explicitly are empty-initialized.
When initializing a union, the initializer list must have only one member, which initializes the first member of the union unless a designated initializer is used (since C99).
union { int x; char c[4]; } u = {1}, // makes u.x active with value 1 u2 = { .c={'\1'} }; // makes u2.c active with value {'\1','\0','\0','\0'}
When initializing a struct, the first initializer in the list initializes the first declared member (unless a designator is specified) (since C99), and all subsequent initializers without designators (since C99)initialize the struct members declared after the one initialized by the previous expression.
struct point {double x,y,z;} p = {1.2, 1.3}; // p.x=1.2, p.y=1.3, p.z=0.0 div_t answer = {.quot = 2, .rem = -1 }; // order of elements in div_t may vary
A designator causes the following initializer to initialize the struct member described by the designator. Initialization then continues forward in order of declaration, beginning with the next element declared after the one described by the designator. | (since C99) |
It's an error to provide more initializers than members.
If the members of the struct or union are arrays, structs, or unions, the corresponding initializers in the brace-enclosed list of initializers are any initializers that are valid for those members, except that their braces may be omitted as follows:
If the nested initializer begins with an opening brace, the entire nested initializer up to its closing brace initializes the corresponding member object. Each left opening brace establishes a new current object. The members of the current object are initialized in their natural order, unless designators are used (since C99): array elements in subscript order, struct members in declaration order, only the first declared member of any union. The subobjects within the current object that are not explicitly initialized by the closing brace are empty-initialized.
struct example { struct addr_t { uint32_t port; } addr; union { uint8_t a8[4]; uint16_t a16[2]; } in_u; }; struct example ex = { // start of initializer list for struct example { // start of initializer list for ex.addr 80 // initialized struct's only member }, // end of initializer list for ex.addr { // start of initializer-list for ex.in_u {127,0,0,1} // initializes first element of the union } };
If the nested initializer does not begin with an opening brace, only enough initializers from the list are taken to account for the elements or members of the member array, struct or union; any remaining initializers are left to initialize the next struct member:
struct example ex = {80, 127, 0, 0, 1}; // 80 initializes ex.addr.port // 127 initializes ex.in_u.a8[0] // 0 initializes ex.in_u.a8[1] // 0 initializes ex.in_u.a8[2] // 1 initializes ex.in_u.a8[3]
The initializer list may have a trailing comma, which is ignored.
In C, the braced list of initializers cannot be empty (note that C++ allows empty lists, and also note that a struct in C cannot be empty): | (until C23) |
The initializer list can be empty in C as in C++: | (since C23) |
struct {int n;} s = {0}; // OK struct {int n;} s = {}; // Error until C23: initializer-list cannot be empty // OK since C23: s.n is initialized to 0 struct {} s = {}; // Error: struct cannot be empty
Every expression in the initializer list must be a constant expression when initializing aggregates of any storage duration. | (until C99) |
As with all other initialization, every expression in the initializer list must be a constant expression when initializing aggregates of static or thread-local (since C11) storage duration: The order of evaluation of the subexpressions in any initializer is indeterminately sequenced (but not in C++ since C++11): | (since C99) |
#include <stdio.h> #include <time.h> int main(void) { char buff[70]; // designated initializers simplify the use of structs whose // order of members is unspecified struct tm my_time = { .tm_year=2012-1900, .tm_mon=9, .tm_mday=9, .tm_hour=8, .tm_min=10, .tm_sec=20 }; strftime(buff, sizeof buff, "%A %c", &my_time); puts(buff); }
Possible output:
C++ documentation for Aggregate initialization |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/struct_initialization