你可以对指向另一个对象的char *进行算术运算

时间:2017-12-15 10:33:00

标签: c++ language-lawyer

这是读取普通可复制对象的字节的常用方法

Object obj;
auto p = reinterpret_cast<char*>(&obj);
for(size_t i = 0; i < sizeof(obj); i++)
    consume(p[i]);

问题不在于严格别名,char*允许别名。这个问题来自[expr.add]

  

当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型。如果表达式P指向具有x[i]元素的数组对象x的元素n,则表达式P + JJ + P(其中{{ 1}}具有值J)指向(可能是假设的)元素j if x[i + j];否则,行为未定义。同样,如果0 ≤ i + j ≤ n,表达式P - J指向(可能是假设的)元素x[i − j];否则,行为未定义。

假设元素指的是

  

指向0 ≤ i − j ≤ n元素的数组x的最后一个元素的指针被认为等同于指向假设元素n的指针

也就是说,如果算术是指向数组的指针,结果仍然在其范围内,那么这是合法的。

但是,这里显然没有x[n],我们可以对该指针进行算术运算吗?

请注意,读取对象字节的合法解决方案是char[sizeof(Object)]对象。但是,如果那是唯一的解决方案,那么就要问,为什么如果你几乎无法使用它来允许std::memcpy别名?

1 个答案:

答案 0 :(得分:1)

根据引号,指针算法应该是合法的。 Object实例obj可以被视为char[sizeof(Object)]。因此,它是一个n元素数组(请注意nsizeof(Object))。 Standard允许在此数组的范围内进行指针运算加上超出此数组边界的一个假设元素。这是由于

中的小于或等于符号
  

0≤i+j≤n

表达。

从字面上看,reinterpret_cast<char*> (&obj) + sizeof(Object)很好,因为它指向假设元素a[j],其中j = sizeof(Object)并且小于或等于而不是数组的大小,是sizeof(Object)

所以,答案是肯定的。

否则数组的std::end将为UB。