陣列初始化
當初始化陣列型別的物件時,初始化器必須是字串字面量(可選地用花括號括起來)或花括號括起來的陣列成員初始化器列表
= 字串字面量 |
(1) | ||||||||
= { 表示式 , ... } |
(2) | (直到 C99) | |||||||
= { 指示符(可選) 表示式 , ... } |
(2) | (C99 起) | |||||||
= { }
|
(3) | (自 C23 起) | |||||||
[
常量表達式 ]
=
的陣列指示符(C99 起)已知大小的陣列和未知大小的陣列可以被初始化,但變長陣列 (VLA) 不可以(C99 起)(直至 C23)。 變長陣列只能被空初始化。(C23 起)
所有未顯式初始化的陣列元素都將空初始化。
目錄 |
[編輯] 從字串初始化
字串字面量(可選地用花括號括起來)可以用作匹配型別的陣列的初始化器
- 普通字串字面量和 UTF-8 字串字面量(C11 起)可以初始化任何字元型別(char、signed char、unsigned char)的陣列
- L-字首寬字串字面量可以用於初始化任何與(忽略 cv-限定符)wchar_t 相容的型別的陣列
|
(C11 起) |
字串字面量的連續位元組或寬字串字面量的寬字元,包括終止空位元組/字元,初始化陣列的元素
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'
如果陣列大小已知,它可以比字串字面量的大小小一,在這種情況下,終止空字元被忽略
char str[3] = "abc"; // str has type char[3] and holds 'a', 'b', 'c'
請注意,這種陣列的內容是可修改的,與直接使用 char* str = "abc"; 訪問字串字面量不同。
[編輯] 從花括號括起來的列表初始化
當陣列用花括號括起來的初始化器列表初始化時,列表中的第一個初始化器初始化索引為零的陣列元素(除非指定了指示符)(C99 起),並且每個後續的沒有指示符的(C99 起)初始化器初始化比前一個初始化器初始化的元素索引大一的陣列元素。
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[4] = {1}; // z has type int[4] and holds 1,0,0,0 int w[3] = {0}; // w has type int[3] and holds all zeroes
當初始化已知大小的陣列時(從字串字面量初始化字元陣列除外),提供的初始化器多於元素是錯誤的。
指示符使後續的初始化器初始化由指示符描述的陣列元素。然後初始化按順序向前繼續,從指示符描述的元素之後的下一個元素開始。 int n[5] = {[4]=5,[0]=1,2,3,4}; // holds 1,2,3,4,5 int a[MAX] = { // starts initializing a[0] = 1, a[1] = 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") |
(C99 起) |
當初始化未知大小的陣列時,指定了初始化器的最大下標決定了所宣告陣列的大小。
[編輯] 巢狀陣列
如果陣列的元素是陣列、結構體或聯合體,則花括號括起來的初始化器列表中的相應初始化器可以是這些成員的任何有效初始化器,但它們的花括號可以按以下方式省略
如果巢狀初始化器以開花括號開頭,則整個巢狀初始化器直到其閉花括號初始化相應的陣列元素
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}
如果巢狀初始化器不以開花括號開頭,則僅從列表中取出足夠的初始化器以解釋子陣列、結構體或聯合體的元素或成員;任何剩餘的初始化器都留下來初始化下一個陣列元素
int y[4][3] = { // array of 4 arrays of 3 ints each (4x3 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}
陣列指示符可以巢狀;巢狀陣列的方括號常量表達式遵循外層陣列的方括號常量表達式 int y[4][3] = {[0][0]=1, [1][1]=1, [2][0]=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} |
(C99 起) |
[編輯] 注意
在 C 語言中,陣列初始化器中子表示式的求值順序是不確定序列的(但在 C++ 中不是,C++11 起)
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++ 允許空列表 |
(直至 C23) |
空初始化器可用於初始化陣列 |
(自 C23 起) |
int a[3] = {0}; // valid C and C++ way to zero-out a block-scope array int a[3] = {}; // valid C++ way to zero-out a block-scope array; valid in C since C23
與所有其他初始化一樣,當初始化具有靜態或執行緒區域性儲存持續時間的陣列時,初始化器列表中的每個表示式都必須是常量表達式
[編輯] 示例
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", }; }
[編輯] 參考資料
- C17 標準 (ISO/IEC 9899:2018)
- 6.7.9/12-39 初始化 (p: 101-105)
- 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)
- 6.5.7 初始化