表达式 int *a = {},为什么a为NULL

tan*_*eng 2 c pointers initialization language-lawyer list-initialization

在C语言中,表达式

int *a = {};
Run Code Online (Sandbox Code Playgroud)

编译正常。

为什么我可以将 {} 分配给 int 指针。

{} 主要是什么,变量 a 中有什么。

在调试模式下,为什么变量a为NULL。

如何解释和理解这个表述呢?以及为什么它可以编译?

Vla*_*cow 8

C23标准之前

\n
int *a = {};\n
Run Code Online (Sandbox Code Playgroud)\n

这样的初始化不是 C 标准(尽管某些编译器可以有自己的语言扩展)。根据 C23 标准之前的 C 语法,初始化定义如下

\n
1 initializer:\n    assignment-expression\n    { initializer-list }\n    { initializer-list , }\n
Run Code Online (Sandbox Code Playgroud)\n

可以看出,空括号是不允许的。

\n

在 C23 中允许这样的初始化

\n
1 braced-initializer:\n    { }\n    { initializer-list }\n    { initializer-list , }\n
Run Code Online (Sandbox Code Playgroud)\n

和(C23,6.7.10 初始化)

\n
\n

11 如果具有自动存储持续时间的对象是用空初始化器初始化的,则其值与静态存储持续时间对象的初始化相同。否则,如果未显式初始化具有自动存储持续时间的对象,则其表示形式是不确定的。如果具有静态或线程存储持续时间的对象未显式初始化,或者使用空初始值设定项初始化,则默认初始化:

\n

\xe2\x80\x94如果是指针类型,则初始化为空指针

\n

...

\n
\n

所以在这个声明的C23中

\n
int *a = {};\n
Run Code Online (Sandbox Code Playgroud)\n

指针a被初始化为空指针。

\n

具有自己的语言扩展的编译器也会a在 C23 标准之前按照 C++ 标准初始化将指针初始化为空指针(例如 C++14 标准,8.5.4 列表初始化)

\n
\n

(3.9) \xe2\x80\x94否则,如果初始值设定项列表没有元素,则对该对象进行值初始化。

\n
\n

和(8.5 初始化器)

\n
\n

8 对 T 类型的对象进行值初始化意味着:

\n

...\n(8.4) \xe2\x80\x94 否则,该对象为零初始化

\n
\n

最后

\n
\n

6 对 T 类型的对象或引用进行零初始化意味着:

\n

(6.1) \xe2\x80\x94 如果 T 是标量类型 (3.9),则该对象被初始化为通过将整数文字 0(零)转换为 T 获得的值;

\n
\n

相对于指针,这意味着将它们初始化为空指针,因为在 C 和 C++ 标准中,值为 0 的整型常量是空指针常量:

\n

C 标准

\n
\n

3 值为 0 的整型常量表达式,或此类转换为 void * 类型的表达式,称为空指针常量。67)\n如果将空指针常量转换为指针类型,\n生成的指针(称为空指针)保证与指向任何对象或函数的指针不相等。

\n
\n

和 C++ 标准

\n
\n

1 空指针常量是一个整数文字 (2.13.2),其值为 0 或 std::nullptr_t 类型的纯右值。空指针常量可以\n转换为指针类型;结果是该类型的空指针值,并且可以与对象指针或函数指针类型的所有其他值区分开来。这种转换称为空指针转换。相同类型的两个空指针值应该比较相等。空指针常量到 cv 限定类型的指针的转换是单个转换,而不是指针转换后跟限定转换 (4.4) 的序列。整型空指针常量可以转换为 std::nullptr_t 类型的纯右值。[ 注意:生成的纯右值不是空指针值。\xe2\x80\x94 尾注]。

\n
\n