现代 C 标准中是否存在 nullptr(或等效)之类的东西?
Is there such a thing as nullptr (or equivalent) in modern C standards?
我在一行 C 代码中包括了对 nullptr
的检查。编译器 (gcc) 在使用 -std=c17
和 -std=gnu17
.
时抱怨
在现代 C 标准中是否有 nullptr(或等价物)这样的东西? (C11, C17)
如果不是,那是为什么?
不,C 仍然使用 NULL
作为空指针。
C++ 需要专用的空指针文字,因为它具有重载和模板类型推导。这些特性会被 NULL
混淆,它在 C++ 中扩展为 0
(或类似的东西)。然而,在 C 中这种混淆的风险很小(也许 _Generic
会因此而混淆),此外,C 可以使用 (void*)0
作为空指针,这进一步减轻了这种风险。
最接近 C++ 的 nullptr
的是 C 的 NULL
。哪个may be
- an integer constant expression with the value 0,
- an integer constant expression with the value 0 cast to the type
void*
.
A null pointer constant may be converted to any pointer type; such conversion results in the null pointer value of that type.
正式的 C17 规范声明 stddef.h
header 定义了 NULL
“它扩展为 implementation-defined 空指针常量。” (7.19)
一个空指针常量定义如下(6.3.2.3)
- An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant.) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
- Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null
pointers shall compare equal.
请注意,这会使以下程序产生歧义,因为 NULL
可能是整数常量表达式(函数接受)或 void*
类型(函数不接受)。
#include <stdio.h>
void printInt(int n)
{
printf("%d\n", n);
}
int main(void)
{
printInt(NULL);
}
Which is why nullptr
was introduced in C++11. 对于 C,没有函数重载或类型推导,这不是什么问题。
C 中的空指针是指向“null”的指针对象。您可以通过将指针分配给 空指针常量 来将指针变成空指针。有效的空指针常量是 0
和 (void*)0
。宏 NULL
保证是空指针常量。
然后指针的内部表示变为“空指针”,理论上它可以指向某个奇异系统上不同于零的地址。类似地,NULL
理论上可以扩展为不同于旧的准标准 C 中的零的值。
在创建 C++ 时,Bjarne Stroustrup 发现所有这些都不必要地复杂,并决定“NULL 是 0”(来源:https://www.stroustrup.com/bs_faq2.html#null)。值得注意的是,C++ 是在 C 的第一次标准化之前很久就创建的,因此他的论点与标准 C 的相关性不如与标准前 C 的相关性。
有关 C 中空指针与 NULL 的更多信息,请参阅 What's the difference between null pointers and NULL?
我在一行 C 代码中包括了对 nullptr
的检查。编译器 (gcc) 在使用 -std=c17
和 -std=gnu17
.
在现代 C 标准中是否有 nullptr(或等价物)这样的东西? (C11, C17)
如果不是,那是为什么?
不,C 仍然使用 NULL
作为空指针。
C++ 需要专用的空指针文字,因为它具有重载和模板类型推导。这些特性会被 NULL
混淆,它在 C++ 中扩展为 0
(或类似的东西)。然而,在 C 中这种混淆的风险很小(也许 _Generic
会因此而混淆),此外,C 可以使用 (void*)0
作为空指针,这进一步减轻了这种风险。
最接近 C++ 的 nullptr
的是 C 的 NULL
。哪个may be
- an integer constant expression with the value 0,
- an integer constant expression with the value 0 cast to the type
void*
.A null pointer constant may be converted to any pointer type; such conversion results in the null pointer value of that type.
正式的 C17 规范声明 stddef.h
header 定义了 NULL
“它扩展为 implementation-defined 空指针常量。” (7.19)
一个空指针常量定义如下(6.3.2.3)
- An integer constant expression with the value 0, or such an expression cast to type
void *
, is called a null pointer constant.) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.- Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
请注意,这会使以下程序产生歧义,因为 NULL
可能是整数常量表达式(函数接受)或 void*
类型(函数不接受)。
#include <stdio.h>
void printInt(int n)
{
printf("%d\n", n);
}
int main(void)
{
printInt(NULL);
}
Which is why nullptr
was introduced in C++11. 对于 C,没有函数重载或类型推导,这不是什么问题。
C 中的空指针是指向“null”的指针对象。您可以通过将指针分配给 空指针常量 来将指针变成空指针。有效的空指针常量是 0
和 (void*)0
。宏 NULL
保证是空指针常量。
然后指针的内部表示变为“空指针”,理论上它可以指向某个奇异系统上不同于零的地址。类似地,NULL
理论上可以扩展为不同于旧的准标准 C 中的零的值。
在创建 C++ 时,Bjarne Stroustrup 发现所有这些都不必要地复杂,并决定“NULL 是 0”(来源:https://www.stroustrup.com/bs_faq2.html#null)。值得注意的是,C++ 是在 C 的第一次标准化之前很久就创建的,因此他的论点与标准 C 的相关性不如与标准前 C 的相关性。
有关 C 中空指针与 NULL 的更多信息,请参阅 What's the difference between null pointers and NULL?