更新时间:2023-02-26 13:52:57
否,这不是合法的C ++.仅当您停留在同一数组(或数组末尾)内时,才定义指针算术.
No, this is not legal C++. Pointer arithmetic is only defined if you stay inside the same array (or one past its end).
将具有整数类型的表达式J
添加到指针类型的表达式P
或从中减去时,结果的类型为P
.
When an expression J
that has integral type is added to or subtracted from an expression P
of pointer type, the result has the type of P
.
(4.1)
如果P
计算为空指针值,而J
计算为0
,则结果为空指针值.
(4.1)
If P
evaluates to a null pointer value and J
evaluates to 0
, the result is a null pointer value.
(4.2)
否则,如果P
指向具有n个元素的数组对象x
的元素x[i]
,则表达式P + J
和J + P
(其中J
的值为j
)指向(可能是-如果0≤i+j≤n
,则假定x[i+j]
,如果0≤i−j≤n
,则表达式P - J
指向(可能是假想的)元素x[i−j]
.
(4.2)
Otherwise, if P
points to element x[i]
of an array object x
with n elements, the expressions P + J
and J + P
(where J
has the value j
) point to the (possibly-hypothetical) element x[i+j]
if 0≤i+j≤n
and the expression P - J
points to the (possibly-hypothetical) element x[i−j]
if 0≤i−j≤n
.
(4.3) 否则,行为是不确定的.
(4.3) Otherwise, the behavior is undefined.
(4.1)不适用,因为您未在nullptr
上进行操作. (4.2)不适用,因为您正在使用double*
,因此标准引号中的x
必须是double
数组,即结构的b
成员.根据其余的(4.3),使用指针算法来限制边界是不确定的行为.
(4.1) does not apply because you're not operating on nullptr
s. (4.2) does not apply because you are working with double*
, so x
in the standard quote must be a double
array, i.e. the b
member of your struct. Leaving its bounds with pointer arithmetic, according to the remaining (4.3), is undefined behavior.
您要在此处进行的操作恰恰是一个好的编译器应该(并且将要)在后台进行的操作:
What you are trying to do here is exactly what a good compiler should (and will) do under the hood anyway:
volatile double output;
void bar(std::vector<foo> bar, int innerOffset)
{
for (foo& f : bar)
output = f.b[innerOffset];
}
请注意反汇编如何执行所需的指针算术(因为编译器知道它在目标平台上可以正常工作).这是最里面的循环:
Notice how the disassembly does the pointer arithmetic you want (because the compiler knows that it works on the target platform). Here is the innermost loop:
.L3:
movsd xmm0, QWORD PTR [rax+24+rsi*8]
add rax, 104
movsd QWORD PTR output[rip], xmm0
cmp rdx, rax
jne .L3
104个字节恰好是一个foo
的大小. [rax+24+rsi*8]
表达式免费进行所有附加的指针运算.
104 bytes is exactly how big one foo
is. The [rax+24+rsi*8]
expression is doing all the additional pointer arithmetic for free.