对 NULL、0、nullptr 的解释



考虑代码

#include <iostream>
void foo(int* p)
{
  std::cout << "pointer" << 'n';
}
void foo(int p)
{
  std::cout << "value" << 'n';
}    
int main()
{    
  foo( 0 );    // value
  foo( NULL ); // error: call of overloaded ‘foo(NULL)’ is ambiguous foo( NULL );
  return 0;
}

在这里,我们可以看到为空指针选择正确的重载的问题,这可以通过将nullptr传递给函数foo的第二次调用来解决,但我的问题是关于不同的东西......

据我所知,大多数实现将NULL定义为一个常量文字0,例如 (#define NULL 0 (,因此在编译时预计第二次调用如下所示 - foo( 0 )

但是预处理器给出了一些奇怪的输出(运行g++ -std=c++11 -E main.cpp -o main后(

int main()
{
 foo( 0 );
 foo(
# 25 "main.cpp" 3 4
     __null
# 25 "main.cpp"
          );
 return 0;
}

这里__null是什么?

这是一个内置的int类型吗?

__null是一个

内置的编译器。 GCC 使用它来提供更好的诊断。 问题是你真的想NULL定义为

#define NULL ((void *) 0)

— 就像在 C 中一样。 但是使用当前C++,您将无法编写

int *p = NULL;

因为与 C 不同,没有从 void * 到其他指针类型的隐含转换。 因此,GCC 将__null实现为魔术空指针常量,该常量对任何指针类型都有效,但不是整数。 因此,GCC 可以发出警告

int a = NULL;

否则这是不可能的。

从本质上讲,__nullnullptr的早期版本,但它更保守,因为它只是一个扩展,而不是语言的改变。

最新更新