C++ 空ptr和指针算法

C++ 空ptr和指针算法,c++,c++11,pointers,nullptr,C++,C++11,Pointers,Nullptr,考虑到以下代码,在nullptr上执行指针算法安全吗 我假设将任何偏移量添加到nullptr会导致另一个nullptr,到目前为止,MSVC产生的结果与我预期的一样,但是我有点不确定这样使用nullptr是否安全: float * x = nullptr; float * y = x + 31; // I assume y is a nullptr after this assigment if (y != nullptr) { /* do something */ } 您没有定义“安

考虑到以下代码,在
nullptr
上执行指针算法安全吗

我假设将任何偏移量添加到
nullptr
会导致另一个
nullptr
,到目前为止,MSVC产生的结果与我预期的一样,但是我有点不确定这样使用
nullptr
是否安全:

float * x = nullptr;

float * y = x + 31; // I assume y is a nullptr after this assigment

if (y != nullptr)
{
  /* do something */
}
您没有定义“安全”对您意味着什么,但无论如何,您提出的代码具有未定义的行为。指针算法只允许对指向数组对象的指针值,或者指向超过数组末尾的指针值。(在本规则中,非数组对象被视为一个元素的数组。)


由于null指针永远不是对象的地址或对象的过去地址,因此您的代码永远不会有定义良好的行为。

否,向nullptr添加偏移量不会导致nullptr。这是未定义的行为

。。。在nullptr上执行指针运算安全吗

否,
nullptr
上的算术没有很好地定义,因为它本身不是指针类型(但存在到所有指针类型的NULL值的转换)

)

std::nullptr\u t
是空指针文本的类型,
nullptr
。它是一种独特的类型,本身不是指针类型或指向成员类型的指针


一般来说,任意指针算法(即使是空值)几乎肯定会导致问题-您没有分配内存-您不可以尝试读取或写入

出于比较的目的(例如,最后一个代码),您会很好,但其他情况下,您的代码将导致未定义的行为

如需进一步阅读,请参阅上的维基百科

C++定义了
nullptr
上的两种操作。用于:

float * x=nullptr;
float * y=nullptr;
  • x+/-0=x

  • x-y=0//注意x和y的类型相同


  • 您不能对未定义的内容进行假设,因此不应该这样做。

    添加非零偏移量不会导致空PTR是正确的。然而,对空指针添加/减去0是很好定义的,并且导致空指针(这是C和C++中的一个特定的区别,这是未定义的)。a++即使我不取消引用指针,UB是否仍然有效?你能给出一个参考吗?@tobi303:没有参考,因为标准不必明确声明它是未定义的。[expr.add]/5仅为指向数组的指针(或指向对象的指针,充当1的数组)定义指针+整数的行为。如果指针不指向数组,则根据定义,行为是未定义的(除了添加0的情况,[expr.add]/8定义了所有指针)。@tobi303 UB不是指“崩溃”,而是指“我们没有定义它的作用”。事实上,编译器可以积极地优化和检测UB,并导致您的程序异常运行。优化的一个流派是“由于UB不能发生在格式良好的程序中,任何导致UB的逻辑链都可以作为一种可能性安全地消除,如果检查代码,则跳过显式的
    ”。简而言之,UB可能导致时间旅行错误,远离UB的代码的行为方式与您编写的代码不匹配。@Nicolas,谢谢。像[expr.add]/5这样的东西是我在请求reference@Yakk我知道(或多或少)UB的意思,我只是不知道
    int*a;++
    在1小时前是UB实际上,还定义了第三个操作:
    x==y
    。这似乎微不足道,但实际上意味着只有一个空指针值。关于这一点,有一篇有趣的帖子:我不确定你第二段中的逻辑:指针算法不会导致读取或写入内存。内存与OP的问题无关。这更多的是关于OP的任意部分端问题。我将对此进行清理。这与clang和gcc不同,
    float*a=nullptr;断言(a==nullptr);a++;断言(a!=nullptr)。向
    nullptr
    添加内容不会导致这些编译产生
    nullptr
    。我不知道它是否是UB。一句简短的评论,因为没有答案包含:实际上,指针是内存地址。如果您天真地将偏移量31添加到空指针,则会获得一个指向内存地址
    31
    的指针。这不是空指针。编译器完全可以这样做。如果将null pointer+offset定义为null指针,则编译器必须在那里添加一些条件跳转。因为委员会关心效率,所以标准并不要求在向空指针添加非零偏移量时发生什么。
    float * x=nullptr;
    float * y=nullptr;