According to C++ Standard, a reinterpret_cast
of a pointer T*
to some other type pointer Q*
can change or not change the pointer value dep
class A1 { int a1; };
class A2 { int a2; };
class B: public A1, public A2 { };
#define DBG(val) cout << #val << ": " << val << endl
// test code
B b;
DBG(&b); // prints 0x42
void *p_blank = &b;
DBG(p_blank); // prints 0x42
A2 *p_a2 = &b;
DBG(p_a2); // prints 0x46
void *p_reinterpreted = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted); // prints 0x42
A2 *p_reinterpreted2 = reinterpret_cast<A2*>(&b);
DBG(p_reinterpreted2); // prints 0x42
A2 *p_a2 = &b
means give me the pointer to an A2 object within the B object.
reinterpret_cast<A2*>(&b)
means give me the pointer to b and treat it as an A2 pointer.
The result of this reinterpret_cast has the type 'pointer to A2', therefore it produces no warning when assigned to a void* variable (or to a A2* variable).
The most likely source of trouble is on a vector machine where scalar operations are defined in terms of vectors, and a scalar pointer consists of a pointer to vector with an index into the vector. Historically the original Cray architecture was like this and it caused headaches. Nowadays you might see something like that on a GPU, but I can't point something specific off the top of my head.
The most likely effect is truncation as the destination pointer type lacks bits to specify the index part. C++11 gives a nod in this direction by allowing any pointer types to be reinterpret_cast
ed as long as they have same alignment requirements. The bits "zeroed" by stringent alignment are allowed to not exist.
An object pointer can be explicitly converted to an object pointer of a different type. When a prvalue v of type “pointer to T1” is converted to the type “pointer to cv T2”, the result is
static_cast<cv T2*>(static_cast<cv void*>(v))
if both T1 and T2 are standard-layout types (3.9) and the alignment requirements of T2 are no stricter than those of T1, or if either type is void. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. The result of any other such pointer conversion is unspecified.
I don't think the question is meaningfully different for C++ versus C pointer casts. From this answer I quote only one of the examples:
The Eclipse MV series from Data General has three architecturally supported pointer formats (word, byte, and bit pointers), two of which are used by C compilers: byte pointers for
char*
andvoid*
, and word pointers for everything else
That suggests a reinterpret_cast<Word_Aligned_Type*>(char*)
could lose its sense of which character/byte in the word was being pointed at, making the operation irreversible.
Note that when the standard states that it can or cannot possibly do something, it does not mean that there is any current implementation that has that behavior, only that they could.
The closest that I can think of is an architecture where type alignment was required by the hardware, and an implementation that decided to correct alignment if needed. Something like:
aligned8 var;
aligned1 *p = reinterpret_cast<aligned1*>(&var);
aligned1 *q = p + 1; // assuming aligned 1 size is not multiple of 8
aligned8 *a = reinterpret_cast<aligned8*>(q); // [1]
There could be a requirement that for a
to be a valid pointer it has to address a memory position multiple of 8, while the argument q
with lesser alignment requirements could point to any memory address.
Reinterpret_cast will never return a different address - it is required to copy the exact address.
In cases of multiple inheritance, like David Rodriguez said, taking the address of one of the bases may return an address that has an offset to the address of the first base. Reinterpret_cast will return that offset address, but if you treat it as the upcast address, hell will ensue.
For upcasting, static_cast can return an different address than the one given. If the address you have is one of the bases, and that address is being at an offset to the first base address, static_cast will return a valid address for the upcasted object, which is equal to the address of the first base and thus not equal to the pointer passed.
To make it short: reinterpret_cast gives you the same address, always. Static_cast and dynamic_cast may return a different address, e.g. in certain cases involving multiple inheritance.
The difference between static_cast and dynamic_cast is that static_cast does not check whether the pointer you give it is the right object for the cast, so be sure of that before calling it.