1

A certain tutorial for the Win32 API uses this line to transform the lParam argument from a WM_CREATE message in the main window procedure into a CREATESTRUCT*:

reinterpret_cast<CREATESTRUCT*>(lParam)  // Method 1

I've read elsewhere that reinterpret_cast is dangerous and results in undefined behavior, lightning bolts, and whatnot.


I've used a more conventional cast which the compiler doesn't complain about:

(CREATESTRUCT*) lParam // Method 2

Is there a reason the author of the tutorial did it their way?

And, I'm sure there's a better way than mine?

Ben
  • 54,723
  • 49
  • 178
  • 224
  • To know which cast use, you shoud check out [this wiki post](http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-and-reinterpret-cast-be-used), I always read it whenerver I have doubt on cast. In your case, I think a static_cast is this cleanest answer, since the "C cast can devolve into a reinterpret cast" (sic) – lucasg Oct 31 '12 at 09:09
  • @georgesl, you cannot static-cast an integer to a pointer. – avakar Oct 31 '12 at 09:10
  • hmm, where is the int ? is it LPARAM ? – lucasg Oct 31 '12 at 09:36
  • @georgesl, yes, `LPARAM` is an integer. – avakar Oct 31 '12 at 10:30
  • @georgesl - thanks, actually that was one of the sparks that triggered the question. – Ben Oct 31 '12 at 11:33

2 Answers2

4

Both constructs are equivalent in this particular case. There is no undefined behavior -- the C++ standard guarantees that reinterpret-casting a pointer to a sufficiently wide integer and back results in the same pointer.

You can safely assume that Windows created the lParam value from the original pointer as if by reinterpret_cast.

avakar
  • 32,009
  • 9
  • 68
  • 103
  • 1
    Also, the `(CREATESTRUCT *)` syntax (aka the *C-style cast*) says "use a `reinterpret_cast` or a `static_cast`, whichever works", so functionally, they are the same, just with less error checking. – Simon Richter Oct 31 '12 at 09:09
  • +1 OK thanks fellas, that's a great help. @SimonRichter - do you have a link for that? Had a quick skim of CREATESTRUCT documentation but no dice. If too much trouble no worries, just curious. – Ben Oct 31 '12 at 11:30
  • @Steve, see [this question](http://stackoverflow.com/questions/1609163/what-is-the-difference-between-static-cast-and-c-style-casting). – Simon Richter Oct 31 '12 at 11:37
1

"(CREATESTRUCT*) lParam" form is called a c-style cast. When this is used the compiler would try all possible ways to convert the expression (lParam - here) to the type (CREATESTRUCT* - here).

Let me explain all possible ways of casting,

  1. Casting from "const/volatile T" to T - in C++ a programmer picks this way using const_cast
  2. Casting from "T" to "R" where T and R are related. E.g. like int/char, Car/Vehicle etc. - in C++ a programmer picks this way of casting using static_cast.
  3. Casting from "T" to "R" where T and R are related, along with runtime check. E.g. T = Vehicle and R = Car, conversion from T type object to R type object is valid statically but in reality (at runtime) compiler (through hidden code) has to check if the object being type-casted is indeed a Car or a derivative of Car. - in C++ a programmer picks this way of casting using dynamic_cast.
  4. Casting from "U" to "V" where U and V are unrelated. - in C++ a programmer picks this way of casting using reinterpret_cast.

If a c-style cast is used in C++ by a programmer, he is telling the compiler to try all possible ways to convert/perceive an expression to/as a particular type.

The only reason c-style cast is dangerous is because the real intention of the programmer is not properly conveyed to the compiler and fellow programmers who would be reading the code. Sometimes a programmer may only have meant a static_cast and not reinterpret_cast but using a c-style cast would cause an error at run-time which could have been caught at compile time. Because compiler error would occur if the programmer uses static_cast on unrelated types.

And user defined cast operators affects some behaviors a bit more (esp. static_cast) but does not change the fundamentals.

nanda
  • 804
  • 4
  • 8
  • Thanks @nanda. I'm a little torn who to accept but I'm going with your answer since it explains both sides of my question. – Ben Oct 31 '12 at 11:32