I hear that reinterpret_cast
is implementation defined, but I don't know what this really means. Can you provide an example of how it can go wrong, and it goes wrong, is it better to use C-Style cast?
C-style casts can be used to convert any type into any other type, potentially with unsafe results (such as casting an integer into a pointer type). (<type>)<value> This example casts an int to a double for the purpose of avoiding truncation due to integer division: double result = (double)4/5; Popular pages.
Purpose for using reinterpret_cast It is used when we want to work with bits. If we use this type of cast then it becomes a non-portable product. So, it is suggested not to use this concept unless required. It is only used to typecast any pointer to its original type.
In short: static_cast<>() gives you a compile time checking ability, C-Style cast doesn't. static_cast<>() is more readable and can be spotted easily anywhere inside a C++ source code, C_Style cast is'nt. Intentions are conveyed much better using C++ casts.
The C-style cast isn't better.
It simply tries the various C++-style casts in order, until it finds one that works. That means that when it acts like a reinterpret_cast
, it has the exact same problems as a reinterpret_cast
. But in addition, it has these problems:
reinterpret_cast
, a const_cast
or a static_cast
, and those do very different things)reinterpret_cast
is easy to find, which is good, because casts are ugly and should be paid attention to when used. Conversely, a C-style cast (as in (int)42.0
) is much harder to find reliably by searchingTo answer the other part of your question, yes, reinterpret_cast
is implementation-defined. This means that when you use it to convert from, say, an int*
to a float*
, then you have no guarantee that the resulting pointer will point to the same address. That part is implementation-defined. But if you take the resulting float*
and reinterpret_cast
it back into an int*
, then you will get the original pointer. That part is guaranteed.
But again, remember that this is true whether you use reinterpret_cast
or a C-style cast:
int i; int* p0 = &i; float* p1 = (float*)p0; // implementation-defined result float* p2 = reinterpret_cast<float*>(p0); // implementation-defined result int* p3 = (int*)p1; // guaranteed that p3 == p0 int* p4 = (int*)p2; // guaranteed that p4 == p0 int* p5 = reinterpret_cast<int*>(p1); // guaranteed that p5 == p0 int* p6 = reinterpret_cast<int*>(p2); // guaranteed that p6 == p0
It is implementation defined in a sense that standard doesn't (almost) prescribe how different types values should look like on a bit level, how address space should be structured and so on. So it's really a very platform specific for conversions like:
double d; int &i = reinterpret_cast<int&>(d);
However as standard says
It is intended to be unsurprising to those who know the addressing structure of the underlying machine.
So if you know what you do and how it all looks like on a low-level nothing can go wrong.
The C-style cast is somewhat similar in a sense that it can perform reinterpret_cast, but it also "tries" static_cast first and it can cast away cv qualification (while static_cast and reinterpret_cast can't) and perform conversions disregarding access control (see 5.4/4 in C++11 standard). E.g.:
#include <iostream> using namespace std; class A { int x; }; class B { int y; }; class C : A, B { int z; }; int main() { C c; // just type pun the pointer to c, pointer value will remain the same // only it's type is different. B *b1 = reinterpret_cast<B *>(&c); // perform the conversion with a semantic of static_cast<B*>(&c), disregarding // that B is an unaccessible base of C, resulting pointer will point // to the B sub-object in c. B *b2 = (B*)(&c); cout << "reinterpret_cast:\t" << b1 << "\n"; cout << "C-style cast:\t\t" << b2 << "\n"; cout << "no cast:\t\t" << &c << "\n"; }
and here is an output from ideone:
reinterpret_cast: 0xbfd84e78 C-style cast: 0xbfd84e7c no cast: 0xbfd84e78
note that value produced by reinterpret_cast is exactly the same as an address of 'c', while C-style cast resulted in a correctly offset pointer.
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