Friday, May 16, 2014

Tips and Tricks: Proper way of "reinterpret casting"

Hello!


This tutorial doesn't talk about a Qt programming tip, but of a matter of general concern in C++ (and some in C) programming: type casting.


Concept and general knowledge

To remember the concept, type casting means to interpret a given data as a different type from the one it's currently being hold, like making a unsigned char variable be seen as a signed integer.

There are various types of casting in C++ (which also includes C casting) and the best explanation I ever found about them may be found in this stackoverflow thread.

Reinterpret casting correctly

The most accepted answer in the stackoverflow thread linked above notes that there is a particular casting method, namely reinterpret_cast, which is particularly bad to use. MSDN article about casting notes:

We recommend that you not use reinterpret_cast because neither a compile-time check nor a run-time check is performed. In the worst case, a reinterpret_cast makes it possible for programming errors to go undetected at development time and cause subtle or catastrophic errors in your program’s behaviour.
The remark is followed by a generally accepted advice:

Therefore, we recommend that you use reinterpret_cast only in those rare cases when you must cast between unrelated types and you know that the cast will succeed.

And in another link:

Unless the desired conversion is inherently low-level, you should use one of the other cast operators.
The question is: should we never, then, use reinterpret_cast? And what about when we actually need it?


The best solution to this problem I found came from a thread in a LinkedIn group, namely C++ Developers Group. When discussing about failure when doing type casting, user Evgeny P., a software development consultant at Visual Technology Services Ltd. at the time, suggested that instead of using normal reinterpret_cast


T1 *p1= ... ;
T2 *p2=reinterpret_cast<T2*>(p1);
, one should prefer do a static_cast after a cast to void*:

T1 *p1= ... ;
void *pV=p1;
T2 *p2=static_cast<T2*>(pV);

or, in case the user wants a more "clear intent code", one should use something like:

template<typename To> inline
To *unrelated_pointer_cast(void *from)
{
    return static_cast<To*>(from);
}

Req *msg = unrelated_pointer_cast<Req>(const_cast<U8*>(msgPtr));

Conclusion

Good programming means not simply "code that works", but "code that works well", and one way of archiving this is by using ways of doing tasks in a better way, if so is available, either by means of using safer code or another way. With his tip, one may improve his code by avoiding the use of reinterpret_cast without having to change anything else in his work.


God bless you! Have a nice day!

No comments:

Post a Comment