tags:

views:

198

answers:

5

I have been reading a lot about C++ casting and I am starting to get confused because I have always used C style casting.

I have read that C style casting should be avoided in C++ and that reinterpret_cast is very very dangerous and should not be used whenever there is an alternative. On the contrary to not using reinterpret_cast, I have seen it used many times on MSDN in their sample code. This leads me to ask my first question, when is it ok to use reinterpret_cast?

For example:

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
   switch (Msg)
   {
      case WM_CREATE:
      {
          LPCREATESTRUCT lpCreateStruct = reinterpret_cast<LPCREATESTRUCT>(lParam); 
          return 0;
      }
   }

   ...
}

If that is not ok, then how would I cast the LPARAM value to a pointer using only static, dynamic, and/or const casting?

Also: If reinterpret_cast is not portable, how would I rewrite it to be portable (for good practice)

+7  A: 

Using reinterpret_cast is acceptable if you know that the pointer was originally of the destination type. Any other use is taking advantage of implementation-dependent behavior, although in many cases this is necessary and useful, such as casting a pointer to a structure into a pointer to bytes so that it can be serialized.

It is considered dangerous because it does no checking, either at compile-time or at runtime. If you make a mistake, it can and will crash and burn horribly, and be difficult to debug. You are essentially telling the compiler "I know better than you what this actually is, so just compile the code and let me worry about the consequences."

MikeP
Serializing structs that way is a bad idea (even if very often done), but that's a topic for another question.
Tronic
+4  A: 

The reason you see it on MSDN is because the Win32 API is a C API, but people insist on giving examples in C++.

Reinterpret cast is fine when you're writing code that interfaces with other libraries. It should be avoided within your own app.

Frank Krueger
+2  A: 

Not to disrespect MSDN, but MSDN is not the best place to go for proper C++ coding.

One reason to use reinterpret_cast is when you're casting to/from opaque datatypes. reinterpret_cast is not "dangerous" it's just that it's easy to screw up and lead to problems in your code, which is why it should be avoided.

The reason why the C++ style casts are preferred are that, static_cast is typesafe, and all casting times are easier to search for.

Programmers [incorrectly] often use casts to "cast off compiler warnings" such as converting from unsigned to signed integers, or from a 32bit integer to an 8bit one.

Alan
+1. MSDN is chock full of MS-isms. Good books by Scott Meyers and Herb Sutter (though he's now at MS, he's an excellent writer and has lots of great advice on writing good C++) are better places to cement one's understanding of good C++ practice.
Matt Curtis
@Matt Curtis -- I find the more annoying part about MSDN is that the MS-isms are inconsistently applied. Quality varies a lot with their examples. Generally speaking, though, you shouldn't be copy-pasting their examples; it may give you a rough idea but you should adapt those ideas to whatever coding style is used in the project you're working on.
asveikau
+1  A: 

Essentially reinterpret_cast is "safe" with C structures and basic types (baring plain mistakes like casting int to a pointer and back, which works on ILP32 architecture but breaks on LP64 one.) A C structure doesn't have anything in it, except possible padding for alignment, that you didn't declare.

reinterpret_cast is not safe with C++ polymorphic types since compiler inserts data items into your class - things like pointers to virtual tables and pointers to virtual base classes. Other C++ casts take care of adjusting these when, say, down-casting from pointer to base class to pointer to derived class, reinterpret_cast and C-style casts don't.

Nikolai N Fetissov
+3  A: 

This is an example of programming the Windows Platform SDK, a C API, with C++. The window procedure only has the WPARAM and LPARAM parameters and if you need to pass a pointer to a structure through a window message, it has to be cast. This is a perfectly acceptable use of reinterpret_cast<> in my opinion. You cannot avoid a cast because the SDK you are writing to, which is not your code, was not designed for C++, much less type-safety, and needs the casting to provide generic parameter types with a C binding.

The reinterpret_cast<> here is a flag that lets you know you need to be careful, but it is not to be avoided at all costs.

If, on the other hand, you controlled both sides of the code, the API and the consumer, it would be better to make an API that was type-safe and did not require the consumer to perform casts to use it correctly.

GBegen