cig*_*ien 4 c++ pointers language-lawyer
我的印象是,虽然取消引用不指向有效对象的指针是 UB,但简单地计算此类指针就可以了。
但是,如果我正确理解expr.add[4],则情况并非如此。
那么这些指针计算中哪些是明确定义的?
int a = 42;
int *p = &a;
p; // valid, and obviously ok
p++; // invalid, but ok, because one past the end of 'array' containing 1 element?
p++; // UB ?
Run Code Online (Sandbox Code Playgroud)
这个案子怎么样?
int *p = nullptr;
p; // invalid, and obviously ok (considered one past the end?)
p++; // one past the end? or UB?
Run Code Online (Sandbox Code Playgroud)
在你的第一个例子中,第一个p++
是明确定义的,因为非数组被认为是一个长度的数组。
这是相关报价(basic.compound/3.4):
出于指针算术 ([expr.add]) 和比较 ([expr.rel], [expr.eq]) 的目的,超过 n 个元素的数组 x 的最后一个元素末尾的指针被认为等价于指向 x 的假设数组元素 n 的指针和不是数组元素的类型 T的对象被认为属于具有一个类型 T 的元素的数组。
在 之后p++
,p
它将指向(假设)数组的最后一个(也是唯一一个)元素,这是明确定义的。它不是“无效,但可以”,因为指向对象末尾的指针不是无效指针,basic.compound/3.2:
指针类型的每个值都是以下之一:
[...]
一个指针过去的对象的端
[...]
无效的指针值。
第p++
一个示例中的第二个是 UB,因为结果将指向未定义的假设 (&a)[1] 元素之后。
在您的第二个示例中,p++
是 UB,因为只能将 0 添加到nullptr
( expr.add/4.1 ):
如果 P 计算为空指针值而 J 计算为 0,则结果为空指针值。
[...]
否则,行为是 undefined。