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?
Since void is an incomplete type, it is not an object type. Therefore it is not a valid operand to an addition operation. Therefore you cannot perform pointer arithmetic on a void pointer.
You can perform a limited number of arithmetic operations on pointers. These operations are: Increment and decrement. Addition and subtraction.
We can perform arithmetic operations on the pointers like addition, subtraction, etc. However, as we know that pointer contains the address, the result of an arithmetic operation performed on the pointer will also be a pointer if the other operand is of type integer.
void* ptr = nullptr; The pointer ptr is a void pointer, and we have set it to be a null pointer. We can not perform pointer arithmetic on a void pointer. This is so because, to increase or decrease the pointer's value, pointer arithmetic needs the pointer to know the size of the object it points to.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With