Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you do arithmetic on a char* pointing at another object [duplicate]

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 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; otherwise, the behavior is undefined. Likewise, the expression P - J points to the (possibly-hypothetical) element x[i − j] if 0 ≤ i − j ≤ n; otherwise, the behavior is undefined.

Where hypothetical element refers to

A pointer past the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical element x[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?

like image 737
Passer By Avatar asked Dec 15 '17 10:12

Passer By


People also ask

Why can't I perform arithmetic on void * pointer?

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.

Is arithmetic operations possible with pointer?

You can perform a limited number of arithmetic operations on pointers. These operations are: Increment and decrement. Addition and subtraction.

Which pointer is arithmetic allowed?

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.

Can we do pointer arithmetic on a void pointer?

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.


1 Answers

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.

like image 90
ivaigult Avatar answered Sep 24 '22 22:09

ivaigult