【问题标题】:Can I guarantee that the address of nullptr is always 0?我能保证nullptr的地址总是0吗?
【发布时间】:2020-04-13 22:38:42
【问题描述】:

我知道NULL总是0,但是为什么下面的代码会打印消息?

#include <iostream>

using namespace std;

int main() {
    int* ptr = nullptr;
    if (ptr == 0) {
        cout << "Does it always work?";
    }
    return 0;
}

【问题讨论】:

  • “为什么下面的代码会打印消息” 为什么你不希望它打印出来?
  • "我知道NULL 总是0" 不正确。在我的平台上,NULL 是#define'd 为__null
  • 在汇编级别没有区别。区别在于 C++ 类型语义。
  • @Eljay,根据here的回答“因为NULL是0”,我以为NULL被定义为#define NULL 0
  • @catfour 短语“因为 NULL 为 0”并不意味着 NULL 必须定义为 #define NULL 0。反正有点简化了。

标签: c++ c++11 nullptr


【解决方案1】:

是的。

nullptr 初始化的指针是空指针。

将空指针与文字 0(或 std::nullptr_tnullptr 是;这些都是空指针常量)进行比较总是会产生 true

不过,你不能用任何旧的表达方式来做到这一点;即使整数 i 为 1,i-i 也不是有效的空指针常量,尽管在运行时计算为 0。您的 如果您尝试这样做,程序将无法编译。只有 literal 0 是可以与指针进行比较的有效空指针常量。

此外,这并不一定意味着它的所有位都为零!就像将bool 转换为int 给你0 或1 一样,但bool 的实际底层位可以是任何实现喜欢的位。

最后,请注意您的术语略有偏差;每[support.types.nullptr/1]nullptr本身没有地址可取

【讨论】:

  • 所以,如果我在 for 循环中用零 memset(arr, 0, sizeof arr) 而不是 arr[i]=nullptr 初始化一个指针数组,这并不重要,对吧?
  • @catfour No memset 不安全。这个答案已经说过:“这并不一定意味着它的所有位都为零!”。你应该避免在 C++ 中使用memset。如果您不想编写循环,请改用std::fill
  • @walnut 好的,谢谢,但我不同意“你应该避免在 C++ 中使用memset。改用std::fill”因为memsetstd::fill 快,我们可以使用memset 安全地使用0-1 初始化数组(这在竞争性编程中非常有用)。
  • @catfour 编译器调度 std::fill 调用到 memset 调用,如果可能的话(即对于普通可复制类型):godbolt.org/z/q8-qMF std::fill 的好处是它适用于 every 类型,不仅是可简单复制的类型,而且是类型安全的。性能通常不是使用memset 的好理由。
  • @catfour memset 并不比 std::fill 快。如果可以,std::fill 将调用 memset。这是一个零成本的包装器,可在需要时为您提供类型安全和更多功能。这种“竞争性编程”似乎是一场让最差的代码最快的竞赛。干得好,我猜...?‍♂️
猜你喜欢
  • 2011-08-28
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多