tags:

views:

3807

answers:

5
A: 

It's not that reinterpret_cast is unportable, but it's more that it's extremely dangerous. It's the equivalent of the old-school C style cast, and it basically does a direct byte copy without any regard to type checking or so on.

So yes, to convert between static base types (ie, double <-> float), you'd always use static cast, and to go up or down a class hierarchy, you'd use the dynamic cast. But if you find yourself needing reinterpret_cast, you generally should re-think the code you're about to write. Granted, there are cases where you'll need it, but it should be used exceedingly carefully and rarely.

Edit: Also, you might find this SO question to be helpful

Nik Reiman
No, it's not a direct byte copy. It *is* unportable. The standard doesn't specify that it should perform such a direct byte copy, just that if you reinterpret_cast from A to B to A, you get the original A value. It says *nothing* about what the B value should be.
jalf
Also what should be used to convert between pointer types which have no inheritance hierarchy? That is void* to Type*?
HeretoLearn
Also, reinterpret_cast is *not* the equivalent of a C-style cast. A C-style cast is its own beast and is sometimes (but not always) equivalent to a static_cast.
flodin
Ok, point taken. Can somebody please vote this answer down, so I can at least delete it and claim the "peer pressure" badge? :)
Nik Reiman
A: 

Read the FAQ! Holding C++ data in C can be risky.

In C++, a pointer to an object can be converted to void * without any casts. But it's not true the other way round. You'd need a static_cast to get the original pointer back.

dirkgently
+3  A: 

The meaning of reinterpret_cast is not defined by the C++ standard. Hence, in theory a reinterpret_cast could crash your program. In practice compilers try to do what you expect, which is to interpret the bits of what you are passing in as if they were the type you are casting to. If you know what the compilers you are going to use do with reinterpret_cast you can use it, but to say that it is portable would be lying.

For the case you describe, and pretty much any case where you might consider reinterpret_cast, you can use static_cast or some other alternative instead. Among other things the standard has this to say about what you can expect of static_cast (§5.2.9):

An rvalue of type “pointer to cv void” can be explicitly converted to a pointer to object type. A value of type pointer to object converted to “pointer to cv void” and back to the original pointer type will have its original value.

So for your use case, it seems fairly clear that the standardization committee intended for you to use static_cast.

flodin
Not quite crash your program. The standard offers a few guarantees about reinterpret_cast. Just not as many as people often expect.
jalf
Well, the reinterpret_cast itself would probably not crash, but it could return some bogus the result that, when you try to use it, could cause a crash.
flodin
Not if you use it properly. That is, reinterpret_cast from A to B to A is perfectly safe and well-defined. But the value of B is unspecified, and yes, if you rely on that, bad things could happen. But the cast itself is safe enough, as long as you only used it in the way the standard allows. ;)
jalf
reinterpret_crash<> will NOT crash your code. Other than that few guarantees.
Martin York
lol, I suspect that reinterpret_crash might indeed crash your program. But reinterpret_cast won't. ;)
jalf
<irony>I tried it on my compiler, and somehow, it refused to compile `reinterpret_crash`. No way a compiler bug will stop me from crashing my reinterpreting program. I'll report a bug ASAP!</irony>
paercebal
+16  A: 

The C++ standard guarantees the following:

static_casting a pointer to and from void* preserves the address. That is, in the following, a, b and c all point to the same address:

int* a = new int();
void* b = static_cast<void*>(a);
int* c = static_cast<int*>(b);

reinterpret_cast only guarantees that if you cast a pointer to a different type, and then reinterpret_cast it back to the original type, you get the original value. So in the following:

int* a = new int();
void* b = reinterpret_cast<void*>(a);
int* c = reinterpret_cast<int*>(b);

a and c contain the same value, but the value of b is unspecified. (in practice it will typically contain the same address as a and c, but that's not specified in the standard, and it may not be true on machines with more complex memory systems.

For casting to and from void*, static_cast should be preferred.

jalf
I like the fact that 'b' is undefined. It stops you doing silly things with it. If you cast something to another pointer type you are asking for problems and the fact that you can not depend on it makes you more careful. If you had used static_cast<> above what use is the 'b' anyway?
Martin York
I thought that reinterpret_cast<> guaranteed the same bit pattern. (which is not the same as a valid pointer to another type).
Martin York
@Martin - reinterpret_cast<> is not guaranteed to result in the same bit pattern. "The mapping performed by reinterpret_cast<> is implementation defined." (C++03 5.3.10). However, the standard notes that "it is intended to be unsurprising".
Michael Burr
+7  A: 

One case when reinterpret_cast is necessary is when interfacing with opaque data types. This occurs frequently in vendor APIs over which the programmer has no control. Here's a contrived example where a vendor provides an API for storing and retrieving arbitrary global data:

// vendor.hpp
typedef struct _Opaque * VendorGlobalUserData;
void VendorSetUserData( VendorGlobalUserData p );
VendorGlobalUserData VendorGetUserData();

To use this API, the programmer must cast their data to VendorGlobalUserData and back again. static_cast won't work, you must use reinterpret_cast:

// main.cpp
#include "vendor.hpp"
#include <iostream>
using namespace std;

struct MyUserData {
    MyUserData() : m( 42 ) {}
    int m;
};

int main() {
    MyUserData u;

        // store global data
    VendorGlobalUserData d1;
//  d1 = &u;                                             // compile error
//  d1 = static_cast< VendorGlobalUserData >( &u );      // compile error
    d1 = reinterpret_cast< VendorGlobalUserData >( &u ); // ok
    VendorSetUserData( d1 );

        // do other stuff...

        // retrieve global data
    VendorGlobalUserData d2 = VendorGetUserData();
    MyUserData * p = 0;
//  p = d2;                                              // compile error
//  p = static_cast< MyUserData * >( d2 );               // compile error
    p = reinterpret_cast< MyUserData * >( d2 );          // ok

    if ( p ) { cout << p->m << endl; }
    return 0;
}

Below is a contrived implementation of the sample API:

// vendor.cpp
static VendorGlobalUserData g = 0;
void VendorSetUserData( VendorGlobalUserData p ) { g = p; }
VendorGlobalUserData VendorGetUserData() { return g; }
jwfearn
Yep, that's about the only meaningful use of reinterpret_cast I can think of.
jalf