Home > Software design >  Is there difference between the reinterpret_cast and the static_cast in any pointer-to-pointer conve
Is there difference between the reinterpret_cast and the static_cast in any pointer-to-pointer conve

Time:10-21

cppreference/reinterpret_cast conversion/Explanation says

Unlike static_cast, but like const_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 to static_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 b resolved in run-time(can the bit pattern be changed)?. If so, is there difference between 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.

  • Related