Initialization
对象的 声明 可以通过称为 初始化 的过程提供其初始值。
对于每个 声明符 ,若未省略初始化式,则其可为下列形式之一:
=
表达式
|
(1) | ||||||||
=
{
初始化列表
}
|
(2) | ||||||||
=
{
}
|
(3) | (C23起) | |||||||
其中 initializer-list 是一个非空的逗号分隔的 initializer 列表(可包含可选尾部逗号),每个初始化器具有以下三种可能形式之一:
| expression | (1) | ||||||||
{
initializer-list
}
|
(2) | ||||||||
{
}
|
(3) | (自 C23 起) | |||||||
designator-list
=
initializer
|
(4) | (自 C99 起) | |||||||
|
其中
designator-list
是由数组指示符(形式为
注意:除初始化器外,花括号包围的 initializer-list 还可出现在 复合字面量 中,其表达式形式为:
|
(C99 起) | ||||||||||||||||||||||||||||||||||||
目录 |
说明
初始化器指定对象中存储的初始值。
显式初始化
如果提供了初始化器,请参阅
隐式初始化
如果未提供初始化器:
空初始化
|
当对象通过初始化器 = { } 被显式初始化时,该对象为空初始化。 |
(since C23) |
在某些情况下,若对象未显式初始化,则会进行空初始化,即:
- 指针被初始化为其类型的空指针值
- 整型对象被初始化为无符号零值
- 浮点类型对象被初始化为正零值
- 数组的所有元素、结构体的所有成员以及联合体的首个成员都会递归地进行空初始化,同时所有填充位都被初始化为零
- (在那些空指针值和浮点零具有全零位表示的平台上,静态变量的这种初始化形式通常通过将它们分配在程序映像的 .bss 段中来实现)
注释
当初始化具有静态或线程局部 存储期 的对象时,初始化器中的每个 表达式 必须是 常量表达式 或 字符串字面量 。
初始化器不能用于不完整类型对象、变长数组以及具有链接的块作用域对象的声明。
函数参数的初始值是通过从 函数调用 实参赋值的方式建立的,而非通过初始化。
如果将不确定值用作任何标准库调用的参数,则行为未定义。否则,涉及不确定值的任何表达式的结果均为不确定值(例如 int n ; , n 可能不等于其自身,且在后续读取时可能看似改变了其值)
|
C语言中没有与C++中的 值初始化 直接对应的特殊构造;但是,可以使用 = { 0 } (或在复合字面量中使用 ( T ) { 0 } ) (C99起) 作为替代方案,因为C标准不允许空结构体、空联合体或零长度数组。 |
(C23前) |
|
空初始化器 = { } (或在复合字面量中使用 ( T ) { } )可用于实现与C++中 值初始化 相同的语义。 |
(C23起) |
示例
#include <stdlib.h> int a[2]; // 将a初始化为{0, 0} int main(void) { int i; // 将i初始化为不确定值 static int j; // 将j初始化为0 int k = 1; // 将k初始化为1 // 将int x[3]初始化为1,3,5 // 将int* p初始化为&x[0] int x[] = { 1, 3, 5 }, *p = x; // 将w(包含两个结构体的数组)初始化为 // { { {1,0,0}, 0}, { {2,0,0}, 0} } struct {int a[3], b;} w[] = {[0].a = {1}, [1].a[0] = 2}; // 函数调用表达式可用于局部变量 char* ptr = malloc(10); free(ptr); // 错误:具有静态存储期的对象需要常量初始化器 // static char* ptr = malloc(10); // 错误:VLA无法被初始化 // int vla[n] = {0}; }
参考文献
- C17 标准 (ISO/IEC 9899:2018):
-
- 6.7.9 初始化 (页码: 100-105)
- C11 标准 (ISO/IEC 9899:2011):
-
- 6.7.9 初始化 (p: 139-144)
- C99标准(ISO/IEC 9899:1999):
-
- 6.7.8 初始化(页码:125-130)
- C89/C90 标准 (ISO/IEC 9899:1990):
-
- 6.5.7 初始化
另请参阅
|
C++ 文档
关于
初始化
|