NULL、0、nullptr 的解释

Explanations over 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的早期版本,但更保守,因为它只是一个扩展,而不是语言变化。