首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Array initialization

当初始化一个数组类型的对象时,初始化器必须是一个字符串文字(可选地用大括号括起来)或者是一个由数组成员初始化的大括号括起来的列表:

= string_literal

(1)

= { expression , ... } = { designator(optional) expression , ... }

(2)

(until C99)(since C99)

1)用于字符和宽字符数组的字符串字面初始值设定项

2)用逗号分隔的数组元素的初始值表达式列表,可选地使用形式为[constant-expression 的数组指示符] = (自 C99开始)

已知大小的阵列和未知大小的阵列可能被初始化,但不是 VLA。(自 C99以来)。

所有未明确初始化的数组元素都是以与具有静态存储持续时间的对象相同的方式隐式初始化的。

从字符串初始化

字符串文字(可以用大括号括起来)可以用作匹配类型数组的初始值设定项:

  • 普通字符串文字和 UTF-8字符串(因为 C11)可以初始化任何字符类型的阵列(charsigned charunsigned char
  • 带前缀的宽字符串文字可用于初始化任何兼容的类型的数组(忽略 cv 资格) wchar_t

u-prefixed wide string literals can be used to initialize arrays of any type compatible with (ignoring cv-qualifications) char16_t U-prefixed wide string literals can be used to initialize arrays of any type compatible with (ignoring cv-qualifications char32_t

(since C11)

  • 带 u 前缀的宽字符串文字可用于初始化任何兼容类型的数组(忽略 cv 资格) char16_t
  • 带U前缀的宽字符串文字可以用来初始化任何兼容类型的数组(忽略 cv 资格) char32_t

(since C11)

字符串文字的连续字节或宽字符串文字的宽字符(包括终止空字节/字符)初始化数组的元素:

代码语言:javascript
复制
char str[] = "abc"; // str has type char[4] and holds 'a', 'b'. 'c', '\0'
wchar_t wstr[4] = L"猫"; // str has type wchar_t[4] and holds L'猫', '\0', '\0', '\0'

如果数组的大小已知,则它可能比字符串文字的大小小1,在这种情况下,将终止空字符被忽略:

代码语言:javascript
复制
char str[3] = "abc"; // str has type char[3] and holds 'a', 'b', 'c'

请注意,与使用直接访问字符串字面值不同,此数组的内容是可修改的char* str = "abc";

从大括号列表中初始化

当一个数组用初始化器的大括号初始化时,列表中的第一个初始化器初始化索引为0的数组元素(除非指定了指定符号)(自C99开始),并且每个后续的初始化器都没有指定符(自C99开始)初始化索引1处的数组元素大于前一个初始化器初始化的数组元素。

代码语言:javascript
复制
int x[] = {1,2,3}; // x has type int[3] and holds 1,2,3
int y[5] = {1,2,3}; // y has type int[5] and holds 1,2,3,0,0
int z[3] = {0}; // z has type int[3] and holds all zeroes

在初始化已知大小的数组时,提供比元素更多的初始化程序是错误的(除了从字符串文字初始化字符数组时)。

A designator causes the following initializer to initialize of the array element described by the designator. Initialization then continues forward in order, beginning with the next element after the one described by the designator. int n5 = {4=5,0=1,2,3,4} // holds 1,2,3,4,5 int aMAX = { // starts initializing a0 = 1, a1 = 3, ... 1, 3, 5, 7, 9, MAX-5 = 8, 6, 4, 2, 0 } // for MAX=6, array holds 1,8,6,4,2,0 // for MAX=13, array holds 1,3,5,7,9,0,0,0,8,6,4,2,0 ("sparse array")

(since C99)

初始化未知大小的数组时,指定初始化程序的最大下标确定正在声明的数组的大小。

嵌套数组

如果数组的元素是数组,结构体或联合体,则大括号括起来的初始化程序中相应的初始化程序是对这些成员有效的任何初始化程序,除了它们的大括号可以省略如下:

如果嵌套的初始化程序以开始大括号开始,则整个嵌套初始化程序直到其大括号初始化相应的数组元素:

代码语言:javascript
复制
int y[4][3] = { // array of 4 arrays of 3 ints each (4x3 matrix)
    { 1 },      // row 0 initialized to {1, 0, 0}
    { 0, 1 },   // row 1 initialized to {0, 1, 0}
    { [2]=1 },  // row 2 initialized to {0, 0, 1}
};              // row 3 initialized to {0, 0, 0}

如果嵌套的初始化程序不是以大括号开头的话,那么只有列表中的足够的初始化程序可以用来解释子数组 struct struct 或 union 的元素或成员; 任何剩余的初始化器都将被初始化为下一个数组元素:

代码语言:javascript
复制
int y[4][3] = {    // array of 4 arrays of 3 ints each (4x2 matrix)
1, 3, 5, 2, 4, 6, 3, 5, 7 // row 0 initialized to {1, 3, 5}
};                        // row 1 initialized to {2, 4, 6}
                          // row 2 initialized to {3, 5, 7}
                          // row 3 initialized to {0, 0, 0}
 
struct { int a[3], b; } w[] = { { 1 }, 2 }; // array of structs
   // { 1 } is taken to be a fully-braced initializer for element #0 of the array
   // that element is initialized to { {1, 0, 0}, 0}
   // 2 is taken to be the first initialized for element #1 of the array
   // that element is initialized { {2, 0, 0}, 0}

Array designators may be nested; the bracketed constant expression for nested arrays follows the bracketed constant expression for the outer array: int y4 = {0=1, 1=1, 2=1}; // row 0 initialized to {1, 0, 0} // row 1 initialized to {0, 1, 0} // row 2 initialized to {1, 0, 0} // row 3 initialized to {0, 0, 0}

(since C99)

笔记

数组初始值设定项中子表达式的求值顺序在 C 中是不确定的(但在c ++ 11以后,不在 C ++中):

代码语言:javascript
复制
int n = 1;
int a[2] = {n++, n++}; // unspecified, but well-defined behavior,
                       // n is incremented twice (in arbitrary order)
                       // a initialized to {1, 2} and to {2, 1} are both valid
puts((char[4]){'0'+n} + n++); // undefined behavior:
                              // increment and read from n are unsequenced

在 C 中,初始化程序的支撑列表不能为空。C ++允许空列表:

代码语言:javascript
复制
int a[3] = {0}; // valid C and C++ way to zero-out a block-scope array
int a[3] = {}; // invalid C but valid C++ way to zero-out a block-scope array

与所有其他初始化一样,初始化器列表中的每个表达式在初始化静态或线程本地存储持续时间数组时都必须是常量表达式:

代码语言:javascript
复制
static char* p[2] = {malloc(1), malloc(2)}; // error

代码语言:javascript
复制
int main(void)
{
    // The following four array declarations are the same
    short q1[4][3][2] = {
        { 1 },
        { 2, 3 },
        { 4, 5, 6 }
    };
 
    short q2[4][3][2] = {1, 0, 0, 0, 0, 0, 2, 3, 0, 0, 0, 0, 4, 5, 6};
 
    short q3[4][3][2] = {
        {
            { 1 },
        },
        {
            { 2, 3 },
        },
        {
            { 4, 5 },
            { 6 },
        }
    };
 
    short q4[4][3][2] = {1, [1]=2, 3, [2]=4, 5, 6};
 
 
    // Character names can be associated with enumeration constants
    // using arrays with designators:
    enum { RED, GREEN, BLUE };
    const char *nm[] = {
        [RED] = "red",
        [GREEN] = "green",
        [BLUE] = "blue",
    };
}

参考

  • C11标准(ISO / IEC 9899:2011):
    • 6.7.9 / 12-38初始化(p:140-144)
  • C99标准(ISO / IEC 9899:1999):
    • 6.7.8 / 12-38初始化(p:126-130)
  • C89 / C90标准(ISO / IEC 9899:1990):
    • 3.5.7 / 12-初始化

扫码关注腾讯云开发者

领取腾讯云代金券