?
本文檔使用 php中文網(wǎng)手冊 發(fā)布
在初始化struct或union類型的對象時,初始值設(shè)定項必須是成員的非空的,括號括起來的以逗號分隔的初始值設(shè)定項列表:
= {表達式,...} | (直到C99) | |
---|---|---|
= {指定者(可選)表達式,...} | (自C99以來) |
其中指示符是.
表單[
索引中的表單成員和數(shù)組指示符的各個成員標(biāo)識符的序列(空格分隔或相鄰)]
。
所有未明確初始化的成員都會以與具有靜態(tài)存儲持續(xù)時間的對象相同的方式隱式初始化。
初始化聯(lián)合時,初始化程序列表必須只有一個成員,它將初始化聯(lián)合的第一個成員,除非使用了指定的初始化程序(自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'}
當(dāng)初始化一個結(jié)構(gòu)時,列表中的第一個初始化器初始化第一個聲明的成員(除非指定了指定符)(自C99開始),并且沒有指定符的所有后續(xù)初始化器(自C99開始)初始化在先前由表達。
struct point {double x,y,z;} p = {1.2, 1.3}; // p.x=1.2, p.y=1.3, p.z=0.0div_t answer = {.quot = 2, .rem = -1 }; // order of elements in div_t may vary
指示符使下列初始化程序初始化由指定符描述的結(jié)構(gòu)成員。然后按照聲明的順序繼續(xù)初始化,從在指定符描述的聲明之后聲明的下一個元素開始。struct {int sec,min,hour,day,mon,year;} z = {.day = 31,12,2014,.sec = 30,15,17}; //將z初始化為{30,15,17,31,12,2014} | (自C99以來) |
---|
提供比成員更多的初始化器是錯誤的。
如果結(jié)構(gòu)體或聯(lián)合體的成員是數(shù)組,結(jié)構(gòu)體或聯(lián)合體,則大括號括起來的初始化程序中相應(yīng)的初始化程序是對這些成員有效的任何初始化程序,除了它們的大括號可以省略如下:
如果嵌套的初始化程序以一個左大括號開始,則整個嵌套初始化程序直到其大括號初始化相應(yīng)的成員對象。每個左開口大括號建立一個新的當(dāng)前對象。當(dāng)前對象的成員以自然順序進行初始化,除非使用了指示符(自C99起):數(shù)組元素以下標(biāo)順序,聲明順序的struct成員,僅為任何聯(lián)合的第一個聲明成員。當(dāng)前對象內(nèi)的子對象沒有被右括號顯式初始化,它們被隱式初始化。
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 } };
如果嵌套的初始化程序不是以大括號開始,則只有足夠的初始化程序才會考慮成員數(shù)組的元素或成員struct或union; 任何剩余的初始化器都將被初始化為下一個結(jié)構(gòu)成員:
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]
When designators are nested, the designators for the members follow the designators for the enclosing structs/unions/arrays. Within any nested bracketed initializer list, the outermost designator refers to the current object and selects the subobject to be initialized within the current object only. struct example ex2 = { // current object is ex2, designators are for members of example .in_u.a80=127, 0, 0, 1, .addr=80}; struct example ex3 = {80, .in_u={ // changes current object to the union ex.in_u 127, .a82=1 // this designator refers to the member of in_u } }; If any subobject is explicitly initialized twice (which may happen when designators are used), the initializer that appears later in the list is the one used (the earlier initializer may not be evaluated): struct {int n;} s = {printf("a\n"), // this may be printed or skipped .n=printf("b\n")}; // always printed Although any non-initialized subobjects are initialized implicitly, implicit initialization of a subobject never overrides explicit initialization of the same subobject if it appeared earlier in the initializer list: #include <stdio.h> typedef struct { int k; int l; int a2; } T; typedef struct { int i; T t; } S; T x = {.l = 43, .k = 42, .a1 = 19, .a0 = 18 }; // x initialized to {42, 43, {18, 19} } int main(void) { S l = { 1, // initializes l.i to 1 .t = x, // initializes l.t to {42, 43, {18, 19} } .t.l = 41, // changes l.t to {42, 41, {18, 19} } .t.a1 = 17 // changes l.t to {42, 41, {18, 17} } }; printf("l.t.k is %d\n", l.t.k); // .t = x sets l.t.k to 42 explicitly // .t.l = 42 would zero out l.t.k implicitly } Output: l.t.k is 42 However, when an initializer begins with a left open brace, its current object is fully re-initialized and any prior explicit initializers for any of its subobjects are ignored: struct fred { char s4; int n; }; struct fred x = { { { "abc" }, 1 }, // inits x0 to { {'a','b','c','\0'}, 1 } 0.s0 = 'q' // changes x0 to { {'q','b','c','\0'}, 1 } }; struct fred y = { { { "abc" }, 1 }, // inits y0 to { {'a','b','c','\0'}, 1 } 0 = { // current object is now the entire y0 object .s0 = 'q' } // replaces y0 with { {'q','\0','\0','\0'}, 0 } }; | (自C99以來) |
---|
任何初始化器中子表達式的評估順序都是非確定的:
int n = 1;struct {int x,y;} p = {n++, n++}; // unspecified, but well-defined behavior: // n is incremented twice in arbitrary order // p equal {1,2} and {2,1} are both valid
在C中,初始化器的支撐列表不能為空(請注意,C ++允許空列表,并且還要注意C中的結(jié)構(gòu)不能為空):
struct {int n;} s = {0}; // OKstruct {int n;} s = {}; // Error: initializer-list cannot be emptystruct {} s = {}; // Error: struct cannot be empty, initializer-list cannot be empty
與所有其他初始化一樣,初始化器列表中的每個表達式在初始化靜態(tài)或線程本地存儲持續(xù)時間數(shù)組時都必須是常量表達式:
static struct {char* p} s = {malloc(1)}; // error
初始化程序列表可能會有一個尾隨逗號,這會被忽略。
struct {double x,y;} p = {1.0, 2.0, // trailing comma OK };
#include <stdio.h>#include <time.h> int main(void){ char buff[70]; // designated initalizers simplify the use of structs whose // order of members is unspecified struct tm my_time = { .tm_year=112, .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);}
可能的輸出:
Sunday Sun Oct 9 08:10:20 2012
C11標(biāo)準(zhǔn)(ISO / IEC 9899:2011):
6.7.9 / 12-38初始化(p:140-144)
C99標(biāo)準(zhǔn)(ISO / IEC 9899:1999):
6.7.8 / 12-38初始化(p:126-130)
C89 / C90標(biāo)準(zhǔn)(ISO / IEC 9899:1990):
3.5.7 / 9-初始化