您可以对指向另一个对象的char *进行算术运算吗 [英] Can you do arithmetic on a char* pointing at another object
问题描述
这是读取平凡可复制对象字节的常用方法
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 + J
和J + P
(其中J
的值为j
)指向(可能是假设的)x[i + j]
元素,如果0 ≤ i + j ≤ n
;否则,行为是不确定的.同样,如果0 ≤ i − j ≤ n
,则表达式P - J
指向(可能是假想的)元素x[i − j]
;否则,行为是不确定的.
假设元素指的是
为此,超出
n
个元素的数组x
的最后一个元素的指针被认为等效于指向假设元素x[n]
的指针
这就是说,仅当算术在指向数组的指针上并且结果仍在其范围内时,这才是合法的.
但是,这里显然没有char[sizeof(Object)]
,我们可以对该指针进行算术运算吗?
请注意,读取对象字节的合法解决方案是std::memcpy
该对象.但是,如果这是仅 的解决方案,它就会问,如果您几乎不能对它做任何事情,为什么还要允许char*
别名呢?
根据引号,指针算法应合法. Object
实例obj
可以视为char[sizeof(Object)]
.因此,它是n
个元素的数组(请注意n
是sizeof(Object)
). Standard允许在此数组的边界内执行指针算术,并在此数组的边界外加上一个假设元素.这是由于
0≤i + j≤n
表达式.
从字面上看,reinterpret_cast<char*> (&obj) + sizeof(Object)
很好,因为它指向假设元素a[j]
,其中j = sizeof(Object)
且它小于或等于数组sizeof(Object)
的大小. /p>
因此,答案是肯定的.
否则,数组的std::end
将是UB.
This is a common way to read the bytes of an trivially copyable object
Object obj;
auto p = reinterpret_cast<char*>(&obj);
for(size_t i = 0; i < sizeof(obj); i++)
consume(p[i]);
The problem isn't with strict-aliasing, char*
is allowed to alias anything. The problem is with this passage from [expr.add]
When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression
P
points to elementx[i]
of an array objectx
withn
elements, the expressionsP + J
andJ + P
(whereJ
has the valuej
) point to the (possibly-hypothetical) elementx[i + j]
if0 ≤ i + j ≤ n
; otherwise, the behavior is undefined. Likewise, the expressionP - J
points to the (possibly-hypothetical) elementx[i − j]
if0 ≤ i − j ≤ n
; otherwise, the behavior is undefined.
Where hypothetical element refers to
A pointer past the last element of an array
x
ofn
elements is considered to be equivalent to a pointer to a hypothetical elementx[n]
for this purpose
Which is to say, it is only legal if the arithmetic is on a pointer pointing at an array, and the result is still within its range.
However, there is clearly no char[sizeof(Object)]
here, can we do arithmetic on that pointer?
Note that a legal solution to reading bytes of an object is to std::memcpy
the object. But if that is the only solution, it begs to ask, why allow char*
aliasing if you can barely do anything with it?
The pointer arithmetic should be legal according to the quotes. An Object
instance obj
can be viewed as char[sizeof(Object)]
. So, it is an array of n
elements (note that n
is sizeof(Object)
). Standard allows to do pointer arithmetic in bounds of this array plus one hypothetical element beyond the bounds of this array. This is due to less or equal sign in the
0 ≤ i + j ≤ n
expression.
Literally, reinterpret_cast<char*> (&obj) + sizeof(Object)
is fine because it points to hypothetical element a[j]
, where j = sizeof(Object)
and it is less or equal than size of the array, which is sizeof(Object)
.
So, the answer is yes.
Otherwise std::end
for arrays would be UB.
这篇关于您可以对指向另一个对象的char *进行算术运算吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!