标准C89需要初始化语句的元素以固定的顺序出现,和被初始化的数组或结构体中的元素顺序一样。
在ISO C99中,你可以按任何顺序给出这些元素,指明它们对应的数组的下标或结构体的成员名,并且GNU C也把这作为C89模式下的一个扩展。这个扩展没有在GNU C++中实现。
为了指定一个数组下标,在元素值的前面写上“[index] =
”。比如:
int a[6] = { [4] = 29, [2] = 15 }; |
相当于:
int a[6] = { 0, 0, 15, 0, 29, 0 }; |
下标值必须是常量表达式,即使被初始化的数组是自动的。
一个可替代这的语法是在元素值前面写上“.[index]
”,没有“=”,但从GCC 2.5开始就不再被使用,但GCC仍然接受。 为了把一系列的元素初始化为相同的值,写为“[first ... last] = value
”。这是一个GNU扩展。比如:
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 }; |
如果其中的值有副作用,这个副作用将只发生一次,而不是范围内的每次初始化一次。
注意,数组的长度是指定的最大值加一。
在结构体的初始化语句中,在元素值的前面用“.fieldname =
”指定要初始化的成员名。例如,给定下面的结构体,
struct point { int x, y; }; |
和下面的初始化,
struct point p = { .y = yvalue, .x = xvalue }; |
等价于:
struct point p = { xvalue, yvalue }; |
另一有相同含义的语法是“.fieldname:
”,不过从GCC 2.5开始废除了,就像这里所示:
struct point p = { y: yvalue, x: xvalue }; |
“[index]
”或“.fieldname
”就是指示符。在初始化共同体时,你也可以使用一个指示符(或不再使用的冒号语法),来指定共同体的哪个元素应该使用。比如:
union foo { int i; double d; }; |
将会使用第二个元素把4转换成一个double
类型来在共同体存放。相反,把4转换成union foo
类型将会把它作为整数i存入共同体,既然它是一个整数。(参考5.24节向共同体类型转换。)
你可以把这种命名元素的技术和连续元素的普通C初始化结合起来。每个没有指示符的初始化元素应用于数组或结构体中的下一个连续的元素。比如,
int a[6] = { [1] = v1, v2, [4] = v4 }; |
等价于
int a[6] = { 0, v1, v2, 0, v4, 0 }; |
当下标是字符或者属于enum
类型时,标识数组初始化语句的元素特别有用。例如:
int whitespace[256] |
你也可以在“=”前面写上一系列的“.fieldname
”和“[index]
”指示符来指定一个要初始化的嵌套的子对象;这个列表是相对于和最近的花括号对一致的子对象。比如,用上面的struct point
声明:
struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 }; |
如果同一个成员被初始化多次,它将从最后一次初始化中取值。如果任何这样的覆盖初始化有副作用,副作用发生与否是非指定的。目前,gcc会舍弃它们并产生一个警告。