假设我们有一个包含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指针只进行比较,而不是解除引用)。
答案 0 :(得分:7)
在[dcl.array]中:
数组类型的对象包含连续分配的非空
N
类型的T
子对象集。
连续意味着类型T
的任何连续子对象之间的偏移量为sizeof(T)
,这意味着n
子对象的偏移量为n*sizeof(T)
。
n < N
的上限来自[expr.add]:
当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型。如果表达式
P
指向具有x[i]
元素的数组对象x
的元素n
, 表达式P + J
和J + P
(其中J
的值为j
)指向(可能是假设的)元素x[i + j]
if0 <= i + j < n
; 否则,行为未定义。
答案 1 :(得分:1)
它始终是正确的,但是您必须依赖于为sizeof
运算符(5.3.3 [expr.sizeof]
)提供的语义,而不是查看指针运算的规则:
应用于引用或引用类型时,结果是引用类型的大小。 当应用于类时,结果是该类对象中的字节数,包括在数组中放置该类型对象所需的任何填充。最派生类的大小应更大比零。 将sizeof应用于基类子对象的结果是基类类型的大小。 应用于数组时,结果是数组中的总字节数。这意味着 n 元素数组的大小 n 乘以元素的大小。
应该清楚的是,只有一个包装将 n 非重叠元素放在n * sizeof(element)
的空间中,即它们是有规则间隔的sizeof (element)
字节分开。在关系运算符部分(5.9 [expr.rel]
)下找到的指针比较规则只允许一个排序:
比较指向对象的指针定义如下:
- 如果两个指针指向同一个数组的不同元素或其子对象,则指向具有较高下标的元素的指针会比较大。