My mental model for a reinterpret_cast
has always been, to treat the sequence of bits of an expression as if they were of a different type, and cppreference (note: this is not a quote from the C++ Standard) seems to agree with that:
Unlike
static_cast
, but likeconst_cast
, thereinterpret_cast
expression does not compile to any CPU instructions. It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type.
Looking for guarantees, I stumbled across a note under [expr.reinterpret.cast]:
[ Note: The mapping performed by
reinterpret_cast
might, or might not, produce a representation different from the original value. — end note ]
That left me wondering: Under which conditions does a reinterpret_cast
produce a value with object representation different from the original value?
Here's an example: if you read the 4th bullet point:
A pointer can be explicitly converted to any integral type large enough to hold all values of its type. The mapping function is implementation-defined. [ Note: It is intended to be unsurprising to those who know the addressing structure of the underlying machine. — end note ]
Now, it is implementation defined, what value of i
will have here:
void *ptr = <some valid pointer value>;
uintptr_t i = reinterpret_cast<uintptr_t>(ptr);
It can be anything, provided that reinterpret_cast
ing i
back we'll get ptr
.
The representation of ptr
and i
could differ. The standard just says that the value of i
should be "unsurprising". Even, if we reinterpret_cast
ptr
to a wider integer (for example, if a pointer is 32-bit, casting to unsigned long long int
), the representation must differ, because the size of the variables differ.
So I think that cppreference description is misleading, because there can be reinterpret_cast
s, which actually need CPU instructions.
Here is another case (found by IInspectable), a comment by Keith Thompson:
The C compiler for Cray vector machines, such as the T90, do something similar. Hardware addresses are 8 bytes, and point to 8-byte words. void* and char* are handled in software, and are augmented with a 3-bit offset within the word -- but since there isn't actually a 64-bit address space, the offset is stored in the high-order 3 bits of the 64-bit word. So char* and int* are the same size, but have different internal representations -- and code that assumes that pointers are "really" just integers can fail badly.
char *
and int *
have different representations on Cray T90, so:
int *i = <some int pointer value>;
char *c = reinterpret_cast<char *>(i);
Here, i
and c
will have differing representations on Cray T90 (and doing this conversion definitely uses CPU instructions).
(I've verified this, chapter 3.1.2.7.1 of Cray C/C++ Reference Manual SR–2179 2.0)
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