是否对未指向序列未定义行为中的元素的指针递增/递减或添加整数值?

Ita*_*iwa 11 c++ pointers pointer-arithmetic language-lawyer

我知道指针(指向数组元素)和迭代器可以递增/递减以遍历元素序列,并且可以在序列中来回跳转元素。

但是如果我增加一个指向单个对象的指针或向它添加一个整数值会发生什么?这是未定义的行为还是可以但我们无法访问该内存?

int x = 551;
int* p = &x;
++p;
--p;
std::cout << *p << '\n';
Run Code Online (Sandbox Code Playgroud)

因为我已经读过我们不应该增加/减少不指向序列或数组中元素的指针。

那么有人可以解释会发生什么以及我的示例是否正常(取消引用指针 p)?谢谢!

Ast*_*ngs -5

概括

\n

即使在进行取消引用之前,您的程序也没有明确定义。

\n
    \n
  • 您可以递增p一次,从而产生一个尾指针。
  • \n
  • 但是,您不能递减一个尾数指针。\n\n
  • \n
\n
\n

标准语

\n

标准中与此功能相关的规则是以数组的形式给出的,但注释提醒我们,出于这些目的,单个对象被视为单元素数组的元素,引用了以下段落,该段落描述了你的指针:

\n
\n

[basic.compound/3]: [..]指向或超过对象末尾的指针类型的值表示该 object46 占用的内存中第一个字节 ([intro.memory]) 或之后的内存中第一个字节的地址分别是对象占用的存储空间的末尾。[..] 出于指针算术([expr.add]) 和比较 ([expr.rel], [expr.eq])的目的,超过n 个元素的数组的最后一个元素末尾的指针被认为是相当于指向假设数组元素n的指针,并且类型不是数组元素的对象被视为属于具有一个类型 元素的数组。xxTT [..]

\n
\n

所以,是的,您可以根据这些规则安全地“获取”尾数指针。不幸的是,之后你不能用它做太多事情,因为指针加法和减法规则是这样定义的:

\n
\n

[expr.add/4]:当J整型表达式与指针类型表达式相加或相减时P,结果的类型为P。

\n
    \n
  • 如果P计算结果为空指针值并J计算为0,则结果为空指针值。
  • \n
  • 否则,ifP指向具有n 个元素的数组对象([dcl.array ]x ),80 的数组元素 i,则表达式P + J和J + P(其中J有值j)指向if 0的(可能假设的)数组元素i+j \xe2\x89\xa4i+j\xe2\x89\xa4n且表达式指向if 0\xe2\x89\xa4i\xe2\x88\ x92j\的(可能是假设的)数组元素i\xe2 \x88\x92j\ xe2\x89\xa4n。xP - Jx
  • \n
  • 否则,行为是未定义的。
  • \n
\n
\n

\xe2\x80\xa6and&x+1甚至不是 object 所呈现的组成数组的元素x。

\n

如果它说“如果P指向具有n个元素的数组对象的(可能是假设的)数组元素i ”x那么你就可以了,因为这会扩展第二个要点中给出的行为以覆盖过去的- 结束指针(这是x每个第一个引号的“假设数组元素”)。但事实并非如此,因此我们陷入了第三个要点,使您的程序具有未定义的行为。

\n