Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do we have reinterpret_cast in C++ when two chained static_cast can do its job?

Say I want to cast A* to char* and vice-versa, we have two choices (I mean, many of us think we've two choices, because both seems to work! Hence the confusion!):

struct A {     int age;     char name[128]; };  A a; char *buffer = static_cast<char*>(static_cast<void*>(&a)); //choice 1 char *buffer = reinterpret_cast<char*>(&a); //choice 2 

Both work fine.

//convert back A *pA = static_cast<A*>(static_cast<void*>(buffer)); //choice 1 A *pA = reinterpret_cast<A*>(buffer); //choice 2 

Even this works fine!

So why do we have reinterpret_cast in C++ when two chained static_cast can do its job?

Some of you might think this topic is a duplicate of the previous topics such as listed at the bottom of this post, but it's not. Those topics discuss only theoretically, but none of them gives even a single example demonstrating why reintepret_cast is really needed, and two static_cast would surely fail. I agree, one static_cast would fail. But how about two?

If the syntax of two chained static_cast looks cumbersome, then we can write a function template to make it more programmer-friendly:

template<class To, class From> To any_cast(From v) {     return static_cast<To>(static_cast<void*>(v)); } 

And then we can use this, as:

char *buffer = any_cast<char*>(&a); //choice 1 char *buffer = reinterpret_cast<char*>(&a); //choice 2  //convert back A *pA = any_cast<A*>(buffer); //choice 1 A *pA = reinterpret_cast<A*>(buffer); //choice 2 

Also, see this situation where any_cast can be useful: Proper casting for fstream read and write member functions.

So my question basically is,

  • Why do we have reinterpret_cast in C++?
  • Please show me even a single example where two chained static_cast would surely fail to do the same job?

  • Which cast to use; static_cast or reinterpret_cast?
  • Cast from Void* to TYPE* : static_cast or reinterpret_cast
like image 522
Nawaz Avatar asked Feb 17 '11 06:02

Nawaz


People also ask

Why do we need reinterpret_cast?

reinterpret_cast is a type of casting operator used in C++. It is used to convert a pointer of some data type into a pointer of another data type, even if the data types before and after conversion are different. It does not check if the pointer type and data pointed by the pointer is same or not.

What is the difference between static_cast Dynamic_cast Const_cast and reinterpret_cast?

Use static_cast as the equivalent of a C-style cast that does value conversion, or when we need to explicitly up-cast a pointer from a class to its superclass. Use const_cast to remove the const qualifier. Use reinterpret_cast to do unsafe conversions of pointer types to and from integer and other pointer types.

What does static_cast do in C?

static_cast is used to convert from pointer to base class to pointer to derived class, or between native types, such as enum to int or float to int. The user of static_cast must make sure that the conversion is safe. The C-style cast does not perform any check, either at compile or at run time.

What is the point of static_cast?

The static_cast operator converts variable j to type float . This allows the compiler to generate a division with an answer of type float . All static_cast operators resolve at compile time and do not remove any const or volatile modifiers.


2 Answers

There are things that reinterpret_cast can do that no sequence of static_casts can do (all from C++03 5.2.10):

  • A pointer can be explicitly converted to any integral type large enough to hold it.

  • A value of integral type or enumeration type can be explicitly converted to a pointer.

  • A pointer to a function can be explicitly converted to a pointer to a function of a different type.

  • An rvalue of type "pointer to member of X of type T1" can be explicitly converted to an rvalue of type "pointer to member of Y of type T2" if T1 and T2 are both function types or both object types.

Also, from C++03 9.2/17:

  • A pointer to a POD-struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.
like image 102
James McNellis Avatar answered Oct 25 '22 08:10

James McNellis


You need reinterpret_cast to get a pointer with a hardcoded address (like here):

int* pointer = reinterpret_cast<int*>( 0x1234 ); 

you might want to have such code to get to some memory-mapped device input-output port.

like image 40
sharptooth Avatar answered Oct 25 '22 08:10

sharptooth