【问题标题】:Explanations over NULL, 0, nullptr关于 NULL、0、nullptr 的解释
【发布时间】:2017-11-11 14:44:41
【问题描述】:

考虑代码

#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 类型吗??

【问题讨论】:

  • 看起来这是特定于实现的(注意__)。你用的是哪个编译器?
  • @user0042 我正在使用g++ 5.4.0
  • gcc.gnu.org/onlinedocs/libstdc++/manual/support.html (最后一段)换句话说,_null 魔术关键字应该完全防止您看到的内容(首先将0 视为整数,然后才将其转换为nullptr).
  • NULL 的内容是实现定义的。所以看起来 gcc 只是使用了某种内在函数。
  • @VTT — 它是特定于实现的,但没有定义实现。标准中“定义的实现”意味着实现需要记录它的作用。

标签: c++ c++11 null g++ null-pointer


【解决方案1】:

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

#define NULL ((void *) 0)

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

int *p = NULL;

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

int a = NULL;

否则这是不可能的。

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

【讨论】:

    猜你喜欢
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-08
    • 2020-10-10
    相关资源
    最近更新 更多