tan*_*eng 2 c pointers initialization language-lawyer list-initialization
在C语言中,表达式
int *a = {};
Run Code Online (Sandbox Code Playgroud)
编译正常。
为什么我可以将 {} 分配给 int 指针。
{} 主要是什么,变量 a 中有什么。
在调试模式下,为什么变量a为NULL。
如何解释和理解这个表述呢?以及为什么它可以编译?
C23标准之前
\nint *a = {};\nRun Code Online (Sandbox Code Playgroud)\n这样的初始化不是 C 标准(尽管某些编译器可以有自己的语言扩展)。根据 C23 标准之前的 C 语法,初始化定义如下
\n1 initializer:\n assignment-expression\n { initializer-list }\n { initializer-list , }\nRun Code Online (Sandbox Code Playgroud)\n可以看出,空括号是不允许的。
\n在 C23 中允许这样的初始化
\n1 braced-initializer:\n { }\n { initializer-list }\n { initializer-list , }\nRun Code Online (Sandbox Code Playgroud)\n和(C23,6.7.10 初始化)
\n\n\n11 如果具有自动存储持续时间的对象是用空初始化器初始化的,则其值与静态存储持续时间对象的初始化相同。否则,如果未显式初始化具有自动存储持续时间的对象,则其表示形式是不确定的。如果具有静态或线程存储持续时间的对象未显式初始化,或者使用空初始值设定项初始化,则默认初始化:
\n\xe2\x80\x94如果是指针类型,则初始化为空指针;
\n...
\n
所以在这个声明的C23中
\nint *a = {};\nRun Code Online (Sandbox Code Playgroud)\n指针a被初始化为空指针。
具有自己的语言扩展的编译器也会a在 C23 标准之前按照 C++ 标准初始化将指针初始化为空指针(例如 C++14 标准,8.5.4 列表初始化)
\n\n(3.9) \xe2\x80\x94否则,如果初始值设定项列表没有元素,则对该对象进行值初始化。
\n
和(8.5 初始化器)
\n\n\n8 对 T 类型的对象进行值初始化意味着:
\n...\n(8.4) \xe2\x80\x94 否则,该对象为零初始化
\n
最后
\n\n\n6 对 T 类型的对象或引用进行零初始化意味着:
\n(6.1) \xe2\x80\x94 如果 T 是标量类型 (3.9),则该对象被初始化为通过将整数文字 0(零)转换为 T 获得的值;
\n
相对于指针,这意味着将它们初始化为空指针,因为在 C 和 C++ 标准中,值为 0 的整型常量是空指针常量:
\nC 标准
\n\n\n3 值为 0 的整型常量表达式,或此类转换为 void * 类型的表达式,称为空指针常量。67)\n如果将空指针常量转换为指针类型,\n生成的指针(称为空指针)保证与指向任何对象或函数的指针不相等。
\n
和 C++ 标准
\n\n\n1 空指针常量是一个整数文字 (2.13.2),其值为 0 或 std::nullptr_t 类型的纯右值。空指针常量可以\n转换为指针类型;结果是该类型的空指针值,并且可以与对象指针或函数指针类型的所有其他值区分开来。这种转换称为空指针转换。相同类型的两个空指针值应该比较相等。空指针常量到 cv 限定类型的指针的转换是单个转换,而不是指针转换后跟限定转换 (4.4) 的序列。整型空指针常量可以转换为 std::nullptr_t 类型的纯右值。[ 注意:生成的纯右值不是空指针值。\xe2\x80\x94 尾注]。
\n