I am little confused with the applicability of reinterpret_cast
vs static_cast
. From what I have read the general rules are to use static cast when the types can be interpreted at compile time hence the word static
. This is the cast the C++ compiler uses internally for implicit casts also.
reinterpret_cast
s are applicable in two scenarios, convert integer types to pointer types and vice versa or to convert one pointer type to another. The general idea I get is this is unportable and should be avoided.
Where I am a little confused is one usage which I need, I am calling C++ from C and the C code needs to hold on to the C++ object so basically it holds a void*
. What cast should be used to convert between the void *
and the Class type?
I have seen usage of both static_cast
and reinterpret_cast
? Though from what I have been reading it appears static
is better as the cast can happen at compile time? Though it says to use reinterpret_cast
to convert from one pointer type to another?
The short answer: If you don't know what
reinterpret_cast
stands for, don't use it. If you will need it in the future, you will know.Full answer:
Let's consider basic number types.
When you convert for example
int(12)
tounsigned float (12.0f)
your processor needs to invoke some calculations as both numbers has different bit representation. This is whatstatic_cast
stands for.On the other hand, when you call
reinterpret_cast
the CPU does not invoke any calculations. It just treats a set of bits in the memory like if it had another type. So when you convertint*
tofloat*
with this keyword, the new value (after pointer dereferecing) has nothing to do with the old value in mathematical meaning.Example: It is true that
reinterpret_cast
is not portable because of one reason - byte order (endianness). But this is often surprisingly the best reason to use it. Let's imagine the example: you have to read binary 32bit number from file, and you know it is big endian. Your code has to be generic and works properly on big endian (e.g. ARM) and little endian (e.g. x86) systems. So you have to check the byte order. It is well-known on compile time so you can writeconstexpr
function:Explanation: the binary representation of
x
in memory could be0000'0000'0000'0001
(big) or0000'0001'0000'0000
(little endian). After reinterpret-casting the byte underp
pointer could be respectively0000'0000
or0000'0001
. If you use static-casting, it will always be0000'0001
, no matter what endianness is being used.First you have some data in a specific type like int here:
Then you want to access the same variable as an other type like float: You can decide between
or
BRIEF: it means that the same memory is used as a different type. So you could convert binary representations of floats as int type like above to floats. 0x80000000 is -0 for example (the mantissa and exponent are null but the sign, the msb, is one. This also works for doubles and long doubles.
OPTIMIZE: I think reinterpret_cast would be optimized in many compilers, while the c-casting is made by pointerarithmetic (the value must be copied to the memory, cause pointers couldn't point to cpu- registers).
NOTE: In both cases you should save the casted value in a variable before cast! This macro could help:
The meaning of
reinterpret_cast
is not defined by the C++ standard. Hence, in theory areinterpret_cast
could crash your program. In practice compilers try to do what you expect, which is to interpret the bits of what you are passing in as if they were the type you are casting to. If you know what the compilers you are going to use do withreinterpret_cast
you can use it, but to say that it is portable would be lying.For the case you describe, and pretty much any case where you might consider
reinterpret_cast
, you can usestatic_cast
or some other alternative instead. Among other things the standard has this to say about what you can expect ofstatic_cast
(§5.2.9):So for your use case, it seems fairly clear that the standardization committee intended for you to use
static_cast
.One use of reinterpret_cast is if you want to apply bitwise operations to (IEEE 754) floats. One example of this was the Fast Inverse Square-Root trick:
https://en.wikipedia.org/wiki/Fast_inverse_square_root#Overview_of_the_code
It treats the binary representation of the float as an integer, shifts it right and subtracts it from a constant, thereby halving and negating the exponent. After converting back to a float, it's subjected to a Newton-Raphson iteration to make this approximation more exact:
This was originally written in C, so uses C casts, but the analogous C++ cast is the reinterpret_cast.
You could use reinterprete_cast to check inheritance at compile time.
Look here: Using reinterpret_cast to check inheritance at compile time
Quick answer: use
static_cast
if it compiles, otherwise resort toreinterpret_cast
.