views:

569

answers:

8

Often, especially in Win32 programming it is required to cast from one opaque type to another. For example:

 HFONT font = cast_here<HFONT>( ::GetStockObject( SYSTEM_FONT ) );

Both static_cast and reinterpret_cast are applicable here and have exactly the same effect since HFONT is a pointer to a dummy struct specifically introduced for defining HFONT and HGDIOBJ returned by GetStockObject() is a void* pointer.

Which one - static_cast or reinterpret_cast - is preferable?

+11  A: 

static_cast is always preferable, avoid doing reinterpret_casts unless absolutely neccessary.

reinterpret_cast is the least typesafe cast.

More information at this website about which casts should be used when.

Salgar
I hate this kind of blanket statement, it is just not true. static_cast is preferable only when doing cast that it should be used for. reinterpret_cast should be used for all dangerous casts so that you can find them in the code quickly. Casting between two pointer types (if they are unrelated) is a reinterpret_cast operation. If there is a relationship then static_cast MAY be more appropriate. In the context of this quetion I would use reinterpret_cast as you are casting from a void*. Using reinterpret_cast is a good way of noteing that this is a potentially dangerous cast (which it is).
Martin York
Okay, so which casts can static_cast be used for that are all that unsafe? static_cast<> is for casts that have some sort of defined meaning, which usually means reasonably safe.
David Thornley
+1  A: 

static_cast would be preferred.

From More Effective C++ by Scott Meyers

This operator [reinterpret_cast] is used to perform type conversions whose result is nearly always implementation-defined. As a result, reinterpret_casts are rarely portable.

The most common use of reinterpret_cast is to cast between function pointer types.

Kris Kumler
But casting an object from a pointer to void* and then back to the same pointer type is guranteed by the standard to work uisng reinterpret_cast. So this point does not really hold.
Martin York
But yes in the general case static_cast<> is prefered.
Martin York
+1  A: 

Since reinterpret_cast is implementation defined, my rule of thumb is: "static_cast where I can, reinterpret_cast where I must".

(other casts aside)

Kaz Dragon
+2  A: 

I think static_cast would be preferable. Here's another stack overflow post that has some more discussion about that as well.

Eric Petroelje
+12  A: 

It's not correct to state the the casts will have the same affect. The casts do two completely different things:

  • static_cast<T>(x) says convert expression x to type T.
  • reinterpret_cast<T*>(&x) says interpret the memory location '&x' as a T*

Consider the following:

struct A1 { int a1; };
struct A2 { int a2; };
struct B : public A1, public A2 {};

void foo (A1 * a1, A2 * a2)
{
  B * b1_a1 = static_cast<B*> (a1);
  B * b2_a1 = reinterpret_cast<B*> (a1);
  B * b1_a2 = static_cast<B*> (a2);
  B * b2_a2 = reinterpret_cast<B*> (a2);

  std::cout << "b1_a1==b1_a2" << (b1_a1==b1_a2) << std::endl;
  std::cout << "b2_a1==b2_a2" << (b2_a1==b2_a2) << std::endl;
}

int main ()
{
  B b;
  foo (&b, &b);
}

This program results in the following output:

g++ -o t t.cc ; ./t
b1_a1==b1_a2: 1
b2_a1==b2_a2: 0

This shows how the static_cast from a2 to b2 correctly adjusted the pointer so that it points to the beginning of b, but the reinterpret_cast did not.

Richard Corden
This is an excellent example.
quark
Yes but the question was about casting from void*. Also note that casting down is OK with static_cast<> but casting up (away from the base class) it is probably more suitable to use dynamic_cast<>
Martin York
@Martin: The question heading is phrased very generally about when the casts have the same behaviour. The detail may use the 'void*' case as an example of such a situation, but if that is the primary motivation for this question then it should be closed as an exact duplicate of http://stackoverflow.com/questions/310451.
Richard Corden
A: 

My normal advice:

reinterpret_cast<> is to be used only as a last resort. You're telling the compiler to throw away all caution, 'remove all the safeties', and trust your word that it is really Ok, no matter what the compiler knows about the code. You should only use it when nothing else will work.

There will be places where they might have the same effect IF you got the code right. If you eventually make changes and introduce a mistake and the cast is not correct anymore, static_cast<> will probably catch it, but reinterpret_cast<> will certainly not.

In this very particular scenario, that last argument doesn't hold as much: The API is imposing the semantics on you; they are well understood semantics; and you are casting a (void *).

Still, I would use static_cast<>, and leave reinterpret_cast<> for places where truly extraordinary circumstances force me to bypass the type safety. This is a "normal" cast that is required because of the C-compatible nature of the API.

(see also my post here for more details on the differences between static_cast<> and reinterpret_cast<>)

Euro Micelli
+1  A: 

Everybody has noted that reinterpret_cast<> is more dangerous than static_cast<>.
This is because reinterpret_cast<> ignores all type information and just assigns a new type without any real processing, as a result the processing done is implementation defined (though usually the bit patterns of the pointers are the same).

The thing everybody fails to mention is that reinterpret_cast<> is a means to document your program. It tells somebody reading the code that we had to compromise something and as a result we have ended up with a dangerous cast, and be careful when you mess with this code.

Use the reinterpret_cast<> to highlight these dangerous areas in the code.

When casting from a void* there is not type information for the cast to work with.
So you are either doing an invalid cast or a casting back to the original type that was previously cast into a void*. Any other type of casting is going to end up with some undefined behavior.

This is the perfect situation to use reinterpret_cast<> as the standard guarantees that casting a pointer to void* and back to its original type using reinterpret_cast<> will work. And by using reinterpret_cast<> you are pointing out to the humans that come along afterwords that something bad is happening here.

Martin York
For some counter points (as pointed out by Shmoopty) checkout the previuos question http://stackoverflow.com/questions/310451. I like the point about static_cast being more restrictive and therefore potentially finds bugs even for these dangerous situations.
Richard Corden
@Richard: How can it find bugs when there is no type information. void* is as little information as a type can have. Also the article you specify, the comments in the answers deals with casting from a know type (T*) to a different known type (U*) via void*. In this situation I completely agree you should NOT use reinterpret_cast for that. But casting from (T*) to void* back to (T*) is what reinterpret_cast is for.
Martin York
@Martin: The set of pointer types that can be converted using reinterpret_cast is larger than the set using static_cast. If modification of some code changes the types so that 'void*' is no longer the to or from type, then in the reinterpret_cast case the code will silently continue to compile (but with undefined behaviour), and in the static_cast case the code will result in a comiple error. IMHO, the latter is preferable.
Richard Corden
@Richard: I see your point (and I like compilation failures). But your arguments is based around a change in the code where reinterpret_cast<void*> is changed into a reinterpret_cast<T*>. This is obviously wrong; when you change the type you should also change the cast used. The point of the reinterpret_cast<> is to point out that you need to change both the type and the cast (simultaniously) and make it easy to find (with automated tools). Using static cast may protect you against this potential (but unlikely problem) but hides the fact that there is dangerous code that does need to be fixed.
Martin York
The only problem I can see is when this is associated with templates, thus allowing the types to be a bit more changable without exposiing the cast as easily. But if you have templated code that is casting back and forward using reinterpret_cast I think you have bigger problems with your fellow developers.
Martin York
+1  A: 

You should really do whatever the win32 documentation says is the right thing to do. That's what's most likely to work and most likely to be forward compatible, unless it's author is utterly clueless I suppose.

Update: I've looked it up. The Win32 documentation uses C style casts. In this case, C++ defines a C style cast to perform a static cast. So the correct answer is: use static_cast. Or a C style cast, but they're generally best avoided.

Daniel James
It's worth remembering that MSDN is inetnded for C developers as well and that might be the reason why it uses C casts. Plus MSDN uses Hungarian notation which is often considered harmful. So I wouldn't do something just because this is what MSDN does.
sharptooth
That's hardly a valid analogy. The variable names that you use is up to you as it has nothing to do with the interface (apart from avoiding names they use for macros, of course). But you have to cast in a way which is compatible with the casts that they use. Obviously, I'm only talking about the return values from win32 functions and not the general case.
Daniel James