初始化聚合类型

聚合类型是结构、联合或数组类型。 如果聚合类型包含聚合类型的成员,则初始化规则以递归方式应用。

语法

initializer:
{ initializer-list } /* 用于聚合初始化 */
{ initializer-list , }

initializer-list:
initializer
initializer-list , initializer

initializer-list这是用逗号分隔的初始值设定项列表。 列表中的每个初始值设定项都是常量表达式或初始值设定项列表。 因此,初始值设定项列表可以嵌套。 此窗体可用于初始化聚合类型的聚合成员,如本节中的示例所示。 但是,如果自动标识符的初始值设定项是单个表达式,则它不需要是常量表达式;它只需要有适当的类型才能分配给标识符。

对于每个初始值设定项列表,常量表达式的值将按顺序分配给聚合变量的相应成员。

如果 initializer-list 值少于聚合类型,则聚合类型的剩余成员或元素将初始化为 0。 未显式初始化的自动标识符的初始值未定义。 如果 initializer-list 值多于聚合类型,则错误结果。 这些规则适用于每个嵌入式初始值设定项列表以及整个聚合。

结构的初始值设定项是同一类型的表达式,或者是其成员(大括号({ })中括起来的初始值设定项列表。 未命名的位字段成员不会初始化。

初始化联合时, initializer-list 必须是单个常量表达式。 常量表达式的值分配给联合的第一个成员。

如果数组的大小未知,初始值设定项的数量决定了数组的大小,并且其类型将完成。 无法指定 C 中的初始值设定项重复,也不能在数组中间初始化元素,而无需提供上述所有值。 如果需要在程序中执行此作,请使用程序集语言编写例程。

初始值设定项的数量可以设置数组的大小:

int x[ ] = { 0, 1, 2 }

但是,如果指定大小并给出错误数量的初始值设定项,编译器将生成错误。

Microsoft 专用

数组的最大大小由 size_t.

结束 Microsoft 专用

例子

此示例显示数组的初始值设定项。

int P[4][3] =
{
    { 1, 1, 1 },
    { 2, 2, 2 },
    { 3, 3, 3,},
    { 4, 4, 4,},
};

此语句声明 P 为四到三个数组,并将第一行的元素初始化为 1,第二行的元素初始化为 2,依此类而过第四行。 第三行和第四行的初始值设定项列表在最后一个常量表达式后面包含逗号。 最后一个初始值设定项列表 ({4, 4, 4,},) 后跟逗号。 允许这些额外的逗号,但不是必需的。 仅需要将常量表达式与彼此分开的逗号以及将一个初始值设定项列表与另一个初始值设定项列表分开的逗号。

如果聚合成员没有嵌入初始值设定项列表,则为子聚合的每个成员分配值。 因此,上一示例中的初始化等效于以下示例:

int P[4][3] =
{
   1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4
};

大括号还可以出现在列表中的单个初始值设定项周围,有助于阐明示例。

初始化聚合变量时,必须注意正确使用大括号和初始值设定项列表。 以下示例更详细地说明了编译器对大括号的解释:

typedef struct
{
    int n1, n2, n3;
} triplet;

triplet nlist[2][3] =
{
    { {  1, 2, 3 }, {  4, 5, 6 }, {  7, 8, 9 } },  /* Row 1 */
    { { 10,11,12 }, { 13,14,15 }, { 16,17,18 } }   /* Row 2 */
};

在此示例中, nlist 声明为 2 到 3 个结构数组,每个结构具有三个成员。 初始化的第 1 行将值赋给第一行 nlist,如下所示:

  1. 第 1 行的第一个左大括号指示编译器初始化第一个聚合成员 nlist (即,) nlist[0]的开头。

  2. 第二个左大括号表示(即结构)nlist[0][0]的第一个聚合成员nlist[0]的初始化是开始的。

  3. 第一个右大括号结束结构 nlist[0][0]初始化;下一个左大括号开始初始化 nlist[0][1]

  4. 该过程一直持续到行尾,右大括号结束初始化 nlist[0]

第 2 行以类似的方式将值分配给第二行 nlist 。 需要将初始值设定项括在行 1 和 2 上的外部大括号集。 以下构造省略外大括号会导致错误:

triplet nlist[2][3] =  /* THIS CAUSES AN ERROR */
{
     {  1, 2, 3 },{  4, 5, 6 },{  7, 8, 9 },   /* Line 1 */
     { 10,11,12 },{ 13,14,15 },{ 16,17,18 }    /* Line 2 */
};

在此构造中,第 1 行的第一个左大括号开始初始化 nlist[0],这是三个结构的数组。 值 1、2 和 3 分配给第一个结构的三个成员。 遇到下一个右大括号(值 3 后),初始化 nlist[0] 完成,并且三结构数组中的两个剩余结构会自动初始化为 0。 同样, { 4,5,6 } 初始化第二行 nlist中的第一个结构。 其余两个 nlist[1] 结构设置为 0。 当编译器遇到下一个初始值设定项列表时( { 7,8,9 } ),它将尝试初始化 nlist[2]。 由于 nlist 只有两行,因此此尝试会导致错误。

在下一个示例中,三 intx 成员分别初始化为 1、2 和 3。

struct list
{
    int i, j, k;
    float m[2][3];
} x = {
        1,
        2,
        3,
       {4.0, 4.0, 4.0}
      };

list 结构中,第一行 m 中的三个元素初始化为 4.0;其余行 m 的元素默认初始化为 0.0。

union
{
    char x[2][3];
    int i, j, k;
} y = { {
            {'1'},
            {'4'}
        }
      };

在此示例中初始化联合变量 y。 联合的第一个元素是数组,因此初始值设定项是聚合初始值设定项。 初始值设定项列表 {'1'} 将值分配给数组的第一行。 由于列表中只显示一个值,因此第一列中的元素将初始化为字符 1,并且行中的其余两个元素默认初始化为值 0。 同样,第二行 x 的第一个元素初始化为字符 4,行中的其余两个元素初始化为值 0。

另请参阅

初始化