【问题标题】:Can you do arithmetic on a char* pointing at another object [duplicate]你能对指向另一个对象的 char* 进行算术运算吗?
【发布时间】:2017-12-15 10:33:00
【问题描述】:

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

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

问题不在于严格的别名,char* 可以给任何东西加上别名。问题在于[expr.add]的这段话

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

假设元素所指的地方

为此目的,通过数组 xn 元素的最后一个元素的指针被认为等效于指向假设元素 x[n] 的指针

也就是说,只有在指向数组的指针上进行算术运算并且结果仍在其范围内时才合法。

但是,这里显然没有char[sizeof(Object)],我们可以对该指针进行算术运算吗?

请注意,读取对象字节的合法解决方案是std::memcpy 对象。但如果那是唯一的解决方案,那么它会问,如果你几乎不能用它做任何事情,为什么还要允许char* 别名?

【问题讨论】:

  • 为什么缺少元素过去是一个问题?对于指针和数组的所有用途,这肯定是真的吗?
  • unsigned char* 算术,当然。 char*我不认为你可以。
  • 很久以前[在一个遥远的星系中]没有void*类型,而是使用char*
  • @OliverCharlesworth 这篇文章说你只能对数组的元素进行算术运算,最后的元素被视为假设元素。我假设这就是你要问的?
  • @Bathsheba 为什么unsigned char* 有什么不同?

标签: c++ language-lawyer


【解决方案1】:

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

中的 less 或 equal 符号

0 ≤ i + j ≤ n

表达式。

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

所以,答案是肯定的。

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

【讨论】:

  • 它到底在哪里说obj 可以“查看”为char[sizeof(Object)]
  • @Passer By 通过查看别名表示。
  • 在哪里说那是允许的?
  • @PasserBy basic.types
  • N unsigned char 不等于 unsigned char[N],即使它们彼此相邻。另外,你应该把它放在答案中。
猜你喜欢
  • 2014-10-02
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
相关资源
最近更新 更多