cppreference/reinterpret_cast conversion/Explanation says
Unlike
static_cast
, but likeconst_cast
, the reinterpret_cast expression does not compile to any CPU instructions (except when converting between integers and pointers or on obscure architectures where pointer representation depends on its type). It is purely a compile-time directive which instructs the compiler to treat expression as if it had the type new-type.
Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.
...
5) Any object pointer type T1* can be converted to another object pointer type cv T2*. This is exactly equivalent tostatic_cast<cv T2*>(static_cast<cv void*>(expression))
(which implies that if T2's alignment requirement is not stricter than T1's, the value of the pointer does not change and conversion of the resulting pointer back to its original type yields the original value). In any case, the resulting pointer may only be dereferenced safely if allowed by the type aliasing rules (see below)
I thought that the reinterpret_cast guaranteed the same bit pattern, and is always compile-time statement . But in the above quote, there is exception on obscure architectures where pointer representation depends on its type, and the conversion of any object pointer type T1
to another object pointer type T2
is exactly equivalent to static_cast<cv T2>(static_cast<cv void*>(expr) )
. for example,
int a = 10;
void* b = static_cast<void*>(&a); // OK.
static_cast<int*>(b) = 20; // OK. back to the original type.
void* b2 = reinterpret_cast<void*>(&a); // char* b2 = static_cast<void*>(static_cast<void*>(&a) );
static_cast<int*>(b2) = 30; // also OK? because the resulting pointer is equivalent to b, so can be back to the original type.
Is If so, is there difference between b
resolved in run-time(can the bit pattern be changed)?.reinterpret_cast
and static_cast
when do any pointer-to-pointer conversion?.
CodePudding user response:
Changes to the bit-pattern of a pointer aren't really quite a rare as implied, nor is the hardware necessarily quite a obscure as implied. The most common situation involves alignment requirements. A fair number of architectures require "natural alignment". That is, an object with a size of N bits also requires N-bit alignment (e.g., a 32-bit object requires 32-bit alignment).
For example:
// address with all the bits set in the least significant byte
char *x = (char *)0xabcdef;
long *y = reinterpret_cast<long *>(x);
long z = *y;
std::cout << (void *)y;
On an x86 machine, y
will usually contain exactly the bit pattern you requested (because x86 imposes few alignment requirements at the hardware level).
But on something like a SPARC, MIPS or Alpha, attempting to dereference a pointer to long with the three least significant bits set will generate a processor fault. That leaves the compiler with a choice: generate a pointer that can't be dereferenced, or clear some of the bits in the pointer. At least a few choose the latter. It's certainly not guaranteed. Some will leave the value as-is, so dereferencing it just produces a processor fault. But others try to make it into a legitimate pointer to a long
by zeroing the three (or so) least significant bits.