I have seen people suggest using static_cast<SomeType*>(static_cast<void*>(p))
rather than reinterpret casting.
I don't understand why this is better, can someone explain?
For the sake of argument here is an example scenario where reinterpret_cast is needed:
DWORD lpNumberOfBytes;
ULONG_PTR lpCompletionKey;
LPOVERLAPPED lpOverlapped;
GetQueuedCompletionStatus(myHandle, &lpNumberOfBytes, &lpCompletionKey, &lpOverlapped, 0);
if(lpCompletionKey == myCustomHandlerKey){
auto myObject = reinterpret_cast<MyObject*>(lpOverlapped); //i know this is really a MyObject
}
This is what I have heard suggested:
auto myObject = static_cast<MyObject*>(static_cast<void*>(lpOverlapped));
Edit: I origionally started my question with In the comments section "asdf" suggests using static_cast instead of reinterpret_cast here http://blogs.msdn.com/b/vcblog/archive/2014/02/04/challenge-vulnerable-code.aspx but in retrospect the fact that my question came from there is irrelevant.
§5.2.10 describes the legal mappings that reinterpret_cast
can perform, and specifies that “No other conversion can be performed”.
The conversion relevant for your example is /7:
A pointer to an object can be explicitly converted to a pointer to a different object type. When a prvalue
v
of type “pointer toT1
” is converted to the type “pointer to cvT2
”, the result isstatic_cast<cv T2*>(static_cast<cv void*>(v))
if bothT1
andT2
are standard-layout types … and the alignment requirements ofT2
are no stricter than those ofT1
. [emphasis mine]
The result of the conversions of any other pointer to object types is “unspecified”.1
This is one of two reasons why reinterpret_cast
is dangerous: its conversion is only well-defined for a subset of pointer to object types, and compilers usually offer no diagnostics about accidental misuse.
The second reason is that the compiler doesn’t even check whether the mapping you are trying to perform is legal in the first place, and which of the many (semantically completely different) mappings is going to be performed.
Better to be explicit and tell the compiler (and the reader) which the intended conversion is that you want to perform. That said, asdf’s comment isn’t quite correct, because not all conversions that you might want to perform via reinterpret_cast
are equivalent to using static_cast<void*>
followed by a static_cast
to the target type.
1 Aside: In a nutshell (and slightly simplified), a “standard layout type” is a type (or array of type) which doesn’t have virtual functions or mixed member visibility, and all its members and bases are also standard layout. The alignment of a type is a restriction on the addresses in memory at which it may be located. For example, many machines require that double
s are aligned at addresses divisible by 8.
asdf
explained it quite well, even if concisely in the linked post.
because the compiler doesn't know CustomImage derives from Image at this point in the program.
Personally I can't be bothered to download rubbish from msdn just to dig in and answer the question. After all it is a coding challenge, you are supposed to figure it out.
My rules for casting in C++ are:
xx_cast<T*>
and not C-style (T*)
, for explicit is better than implicit.
reinterpret_cast<T*>
make sure that cast/uncast are exact mirror, e.g.:.
T* obj = ...;
void* tmp = reinterpret_cast<void*> obj;
T* ref = reinterpret_cast<T*> tmp; // T* obj --> T* ref
Here, you must make sure that obj
and ref
are same exact type, including const qualifiers, class derivation, alignment, type of memory (embedded), absolutely anything you can think of.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With