现代 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)

  1. 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.
  2. 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?