Difference between reinterpret_cast and two successive static_cast through void*

Started by
5 comments, last by Bregma 15 years, 4 months ago
Hi. This is just from my curiosity. I can cast a pointer value to pointer to unrelated type in two ways, by reinterpret_cast or by static_cast'ing to void* and then casting it again.


struct X;
struct Y;

Y* cast1( X* p )
{
    return reinterpret_cast<Y*>(p);
}

Y* cast2( X* p )
{
    return static_cast<Y*>(static_cast<void*>(p));
}



What's the difference between those two, if there's any? Could someone give me explanation? Thanks in advance
I don't like the name std::vector. I'd be happy if it was std::array.
Advertisement
They are equivalent when they work (that is, on objects with compatible memory layouts). When they don't work, they will misbehave differently (reinterpret_cast usually leaves the numeric representation of the pointer as-is, whereas static_cast changes it).
I think there is none, both casts are just unsafe as hell.
Imagine a class that's derrived from two other classes:
class foo{ public: int i; };class bar{ public bool b; };class foobar : public foo, public bar { short n; };

Casting from foobar to foo is no problem with both of your casts, but casting from foobar to bar or the otherway round is going to introduce terrible errors, because the base address is not modified, although it should.
If you don't need to, do not use reinterpret_cast or casts to void and back.

If you're interested in this topic, google for "mutliple inheritance and the this pointer". You should find the right topic in the first results. You will also read that casting to void and back with static_cast will not change the address in any way.
Thanks for your informations

@ ToohrVyk:
Quote:reinterpret_cast usually leaves the numeric representation of the pointer as-is, whereas static_cast changes it

Does that mean static_cast may even change the numeric representation when casting to void* or back? :O

@ SiS-Shadowman:
I agree. I have been killed by void* several times :D Now the only case I use reinterpret_cast is when I declare typesafe handles.
BTW I usually play Byern Munich when I play FIFA

Yet I'd love to hear more opinions.
Thanks
I don't like the name std::vector. I'd be happy if it was std::array.
Quote:Original post by muse1987
Does that mean static_cast may even change the numeric representation when casting to void* or back? :O


It can be, yes. Imagine you have the following:
const float f = 0.123456f;const int i = static_cast <int> (f); // i = 0const float f_ = static_cast <float> (i); // f_ = 0.0f (approximately)


The same applies to all other types. Think of you have a 64bit pointer, that for some reason you have to convert to a 32bit address (maybe to interface with an old library), while it may work (as casting integers like int64_t to int32_t can work), it could end in an epic fail.

So, always when casting pointers, know what you are doing (though most of the time a cast to void* or char* and then back is safe).
Quote:Original post by muse1987
Does that mean static_cast may even change the numeric representation when casting to void* or back? :O


Of course. It's explicitly allowed by the standard:
Quote:C++ Standard, 4.10 §2
An rvalue of type ``pointer to cv T,'' where T is an object type, can be converted to an rvalue of type ``pointer to cv void.'' The result of converting a ``pointer to cv T'' to a ``pointer to cv void'' points to the start of the storage location where the object of type T resides, as if the object is a most derived object (intro.object) of type T (that is, not a base class subobject).


Enjoy.

Quote:Yet I'd love to hear more opinions.
This is not a matter of opinion: by definition, the standard is right, and anyone who disagrees with the standard is wrong. If you'd rather find out yourself, you can find final draft versions of the C++ standard lying around on the web, and look up the definitions of the various casts.
The main difference between casting through pointer-to-void and using interpret_cast<>() is that when you have a bug, grepping for "interpret_cast" will find it immediately whereas casting through pointer-to-void may require a little more effort.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement