T *与char *指针算法

时间:2016-10-05 15:34:48

标签: c++ arrays pointers c++14 language-lawyer

假设我们有一个包含N个T类型元素的数组。

T a[N];

根据C ++ 14标准,我们在哪些条件下有保证

 (char*)(void*)&a[0] + n*sizeof(T) == (char*)(void*)&a[n],  (0<=n<N) ?

虽然许多类型和实现都是如此,但标准在脚注中以一种模糊的方式提到它:

  

§5.7.6,脚注85)另一种接近指针算法的方法......

没有迹象表明这种方式被认为等同于标准的方式。对于实施者而言,这可能是一个提示,它暗示了许多符合要求的实现之一。

编辑:

人们低估了这个问题的难度。

这个问题不是关于你在教科书中可以阅读的内容,而是关于你可以通过使用逻辑和理由从C ++ 14标准中推断出什么。

如果您使用'连续'或'连续',请说明什么是连续的。

虽然T []和T *密切相关,但它们是抽象,T * x N的加法可以通过实现以任何一致的方式定义。

使用指针添加重新排列等式。如果p指向char,则总是使用(§5.7(4))或一元加法定义p + 1,因此我们不会遇到UB。原始包括指针减法,这可能早期导致UB。 (char指针只进行比较,而不是解除引用)。

2 个答案:

答案 0 :(得分:7)

在[dcl.array]中:

  

数组类型的对象包含连续分配的非空   N类型的T子对象集。

连续意味着类型T的任何连续子对象之间的偏移量为sizeof(T),这意味着n子对象的偏移量为n*sizeof(T)

n < N的上限来自[expr.add]:

  

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

答案 1 :(得分:1)

它始终是正确的,但是您必须依赖于为sizeof运算符(5.3.3 [expr.sizeof])提供的语义,而不是查看指针运算的规则:

  

应用于引用或引用类型时,结果是引用类型的大小。 当应用于类时,结果是该类对象中的字节数,包括在数组中放置该类型对象所需的任何填充。最派生类的大小应更大比零。   将sizeof应用于基类子对象的结果是基类类型的大小。 应用于数组时,结果是数组中的总字节数。这意味着 n 元素数组的大小 n 乘以元素的大小。

应该清楚的是,只有一个包装将 n 非重叠元素放在n * sizeof(element)的空间中,即它们是有规则间隔的sizeof (element)字节分开。在关系运算符部分(5.9 [expr.rel])下找到的指针比较规则只允许一个排序:

  

比较指向对象的指针定义如下:

     
      
  • 如果两个指针指向同一个数组的不同元素或其子对象,则指向具有较高下标的元素的指针会比较大。
  •