C
编译器支持
语言
头文件
类型支持
程序工具
变参函数支持
错误处理
动态内存管理
字符串库
算法
数值
日期和时间工具
输入/输出支持
本地化支持
并发支持 (C11)
技术规范
符号索引
[编辑] C 语言
基本概念
关键词
预处理器
语句
表达式
初始化
声明
函数
杂项
C 的历史
技术规范
[编辑] 初始化
显式初始化
隐式初始化
空初始化
标量初始化
数组初始化
结构体和联合体初始化
[编辑]
当初始化数组类型的对象时,初始化器必须是字符串字面量(可选地用花括号括起来)或花括号括起来的数组成员初始化器列表
= 字符串字面量
(1)
= { 表达式 , ... }
(2)
(直到 C99)
= { 指示符(可选) 表达式 , ... }
(2)
(C99 起)
= { }
(3)
(自 C23 起)
1) 字符和宽字符数组的字符串字面量初始化器
2) 以逗号分隔的常量(直至 C99)表达式列表,它们是数组元素的初始化器,可选地使用形如 [ 常量表达式 ] = 的数组指示符(C99 起)
3) 空初始化器空初始化数组的每个元素
已知大小的数组和未知大小的数组可以被初始化,但变长数组 (VLA) 不可以(C99 起)(直至 C23)。 变长数组只能被空初始化。(C23 起)
所有未显式初始化的数组元素都将空初始化。
目录
1 从字符串初始化
2 从花括号括起来的列表初始化
3 嵌套数组
4 注意
5 示例
6 引用
[编辑] 从字符串初始化
字符串字面量(可选地用花括号括起来)可以用作匹配类型的数组的初始化器
普通字符串字面量和 UTF-8 字符串字面量(C11 起)可以初始化任何字符类型(char、signed char、unsigned char)的数组L-前缀宽字符串字面量可以用于初始化任何与(忽略 cv-限定符)wchar_t 兼容的类型的数组
u-前缀宽字符串字面量可以用于初始化任何与(忽略 cv-限定符)char16_t 兼容的类型的数组U-前缀宽字符串字面量可以用于初始化任何与(忽略 cv-限定符)char32_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
与所有其他初始化一样,当初始化具有静态或线程局部存储持续时间的数组时,初始化器列表中的每个表达式都必须是常量表达式
static char* p[2] = {malloc(1), malloc(2)}; // error
[编辑] 示例
运行此代码
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 初始化