603

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_casts are applicable in two scenarios:

  • convert integer types to pointer types and vice versa
  • 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?

Sisir
  • 4,584
  • 4
  • 26
  • 37
HeretoLearn
  • 7,124
  • 6
  • 24
  • 22
  • 24
    `reinterpret_cast` does not happen at run time. They are both compile-time statements. From http://en.cppreference.com/w/cpp/language/reinterpret_cast: "Unlike static_cast, but like const_cast, the reinterpret_cast expression does not compile to any CPU instructions. It is purely a compiler directive which instructs the compiler to treat the sequence of bits (object representation) of expression as if it had the type new_type." – Cris Luengo Mar 03 '17 at 18:44
  • @HeretoLearn, is it possible to add the relevant code pieces from the *.c and *.cpp file? I think it can improve the exposition of the question. – OrenIshShalom Nov 16 '17 at 07:48

11 Answers11

560

The C++ standard guarantees the following:

static_casting a pointer to and from void* preserves the address. That is, in the following, a, b and c all point to the same address:

int* a = new int();
void* b = static_cast<void*>(a);
int* c = static_cast<int*>(b);

reinterpret_cast only guarantees that if you cast a pointer to a different type, and then reinterpret_cast it back to the original type, you get the original value. So in the following:

int* a = new int();
void* b = reinterpret_cast<void*>(a);
int* c = reinterpret_cast<int*>(b);

a and c contain the same value, but the value of b is unspecified. (in practice it will typically contain the same address as a and c, but that's not specified in the standard, and it may not be true on machines with more complex memory systems.)

For casting to and from void*, static_cast should be preferred.

leiyc
  • 903
  • 11
  • 23
jalf
  • 243,077
  • 51
  • 345
  • 550
  • 18
    I like the fact that 'b' is undefined. It stops you doing silly things with it. If you cast something to another pointer type you are asking for problems and the fact that you can not depend on it makes you more careful. If you had used static_cast<> above what use is the 'b' anyway? – Martin York Feb 21 '09 at 21:27
  • 4
    I thought that reinterpret_cast<> guaranteed the same bit pattern. (which is not the same as a valid pointer to another type). – Martin York Feb 21 '09 at 21:37
  • 1
    @Martin - reinterpret_cast<> is not guaranteed to result in the same bit pattern. "The mapping performed by reinterpret_cast<> is implementation defined." (C++03 5.3.10). However, the standard notes that "it is intended to be unsurprising". – Michael Burr Apr 30 '09 at 03:35
  • 49
    the value of `b` is not unspecified anymore in C++11 when using `reinterpret_cast`. And in C++03 a cast of `int*` to `void*` was forbidden to be done with `reinterpret_cast` (although compilers did not implement that and it was impractical, hence was changed for C++11). – Johannes Schaub - litb Oct 28 '11 at 23:20
  • 1
    hmm, true about reinterpret-casting to/from `void*`. I wonder why I thought that was legal when I wrote this. – jalf Oct 29 '11 at 09:29
  • What happens if you mix the two cast? Is that undefined behavior? http://stackoverflow.com/questions/16499683/is-it-unsafe-to-mix-static-and-reinterpret-cast-when-casting-to-and-back-from-vo – David May 11 '13 at 17:20
  • 117
    This does not actually answer the question of "when to use reinterpret_cast". – einpoklum Apr 15 '16 at 17:56
  • 10
    @LokiAstari I think unspecified does not stop you from doing silly things. It only stop you when you remember it's unspecified. Huge difference. Personally I don't like unspecified. Too much to remember. – Helin Wang Jan 30 '17 at 15:54
  • @HelinWang Which is why using of `reinterpret_cast` is a big red flag in your code you know its dangerous and it reminds you to check. `static_cast` does not throw as big a and red a flag and thus is more dangerous because you are not prompted to remember that what you have is really horrendous. – Martin York Jan 30 '17 at 21:07
  • `static_cast` refuses to cast function pointers to `void*` and back. `reinterpret_cast` and C-style casting `(void*)` work for this case. – Binary Mind Jun 12 '17 at 10:18
  • For an example where the value of `b` differs, see (shameless plug) [my answer below](https://stackoverflow.com/a/57942358/2899559). – Avi Ginsburg Sep 15 '19 at 16:50
  • *static_casting a pointer to and from void\* preserves the address.* In the interests of precision: some pointer types cannot safely and portably be cast to and from void*, no matter which kind of cast is used. This is the case for any pointer-to-function type or pointer-to-member-function type. https://isocpp.org/wiki/faq/pointers-to-members#cant-cvt-memfnptr-to-voidptr – Max Barraclough Dec 13 '20 at 18:29
  • So can I use `static_cast` here: `const auto* pItem = (NM_GRIDVIEW*)pNotifyStruct;`? – Andrew Truckle Sep 11 '21 at 07:59
209

One case when reinterpret_cast is necessary is when interfacing with opaque data types. This occurs frequently in vendor APIs over which the programmer has no control. Here's a contrived example where a vendor provides an API for storing and retrieving arbitrary global data:

// vendor.hpp
typedef struct _Opaque * VendorGlobalUserData;
void VendorSetUserData(VendorGlobalUserData p);
VendorGlobalUserData VendorGetUserData();

To use this API, the programmer must cast their data to VendorGlobalUserData and back again. static_cast won't work, one must use reinterpret_cast:

// main.cpp
#include "vendor.hpp"
#include <iostream>
using namespace std;

struct MyUserData {
    MyUserData() : m(42) {}
    int m;
};

int main() {
    MyUserData u;

        // store global data
    VendorGlobalUserData d1;
//  d1 = &u;                                          // compile error
//  d1 = static_cast<VendorGlobalUserData>(&u);       // compile error
    d1 = reinterpret_cast<VendorGlobalUserData>(&u);  // ok
    VendorSetUserData(d1);

        // do other stuff...

        // retrieve global data
    VendorGlobalUserData d2 = VendorGetUserData();
    MyUserData * p = 0;
//  p = d2;                                           // compile error
//  p = static_cast<MyUserData *>(d2);                // compile error
    p = reinterpret_cast<MyUserData *>(d2);           // ok

    if (p) { cout << p->m << endl; }
    return 0;
}

Below is a contrived implementation of the sample API:

// vendor.cpp
static VendorGlobalUserData g = 0;
void VendorSetUserData(VendorGlobalUserData p) { g = p; }
VendorGlobalUserData VendorGetUserData() { return g; }
jwfearn
  • 28,781
  • 28
  • 95
  • 122
  • 9
    Yep, that's about the only meaningful use of reinterpret_cast I can think of. – jalf Feb 21 '09 at 21:36
  • 13
    This may be a late question, but why doesn't the vendor API use `void*` for that? – Xeo Oct 29 '11 at 01:09
  • 28
    @Xeo They don't use void * because then they lose (some) type-checking at compile time. – jesup Aug 14 '14 at 06:17
  • 4
    A practical use case of "opaque" data types is when you want to expose an API to C but write the implementation in C++. ICU is an example of a library that does this in several places. For example, in the spoof checker API, you deal with pointers of type `USpoofChecker*`, where `USpoofChecker` is an empty struct. However, under the hood, whenever you pass a `USpoofChecker*`, it undergoes `reinterpret_cast` to an internal C++ type. – sffc Mar 23 '17 at 08:08
  • @sffc why not exposing the C struct type to the user? – TonySalimi Sep 09 '18 at 08:20
  • @hsalimi because ICU4C is binary-compatible on C APIs; you can swap in any newer ICU4C library version and your binary build on an older version will work. Exposing the struct via public API would mean we could never add new fields to the struct because the struct gets compiled into the client's binary. – sffc Sep 13 '18 at 22:38
  • Your example is Undefined Behavior in C++. You can't reinterpret_cast one struct to another because of strict [type aliasing rules](https://en.cppreference.com/w/cpp/language/reinterpret_cast#Type_aliasing). The only legal form of it is by memcpy, and that's why C++20 std::bit_cast was invented. – Mariusz Jaskółka May 06 '20 at 15:03
  • @jaskmar You can `reinterpret_cast` pointers, though. That's the trick here: vendor's code actually never tries to use `VendorGlobalUserData`'s value, it only takes it from the user code and passes it back. And the user code knows exactly what the correct type of the pointer is, so it can `reinterprete_cast` it back and access the original object, which is defined. – yeputons Oct 21 '20 at 12:13
  • 1
    @yeputons that's the reason why reinterpret_cast'ing `struct_a*->void*->struct_a*` is well-defined. On the other hand, `struct_a*->void*->struct_b*` and direct `atruct_a->struct_b*` isn't. – Mariusz Jaskółka Oct 22 '20 at 10:43
  • @jaskmar Yes, `struct_a* -> struct_b* -> struct_a*` is what happens in the example, isn't it? `VendorGlobalUserData` is a pointer. That's permitted and equivalent to `struct_a* -> void* -> struct_b* -> void* -> struct_a*`, see bullet 5 [here](https://en.cppreference.com/w/cpp/language/reinterpret_cast). – yeputons Oct 23 '20 at 07:47
  • The general rule is that static_cast cannot cast unrelated types. A simple example is `struct { char c; } c; char *pc = reinterpret_cast(&c);`. Static_cast cannot be used here. – Peter - Reinstate Monica Jul 26 '21 at 06:56
189

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) to float (12.0f) your processor needs to invoke some calculations as both numbers have different bit representation. This is what static_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 convert int* to float* with this keyword, the new value (after pointer dereferecing) has nothing to do with the old value in mathematical meaning (ignoring the fact that it is undefined behavior to read this value).

Be aware that reading or modifying values after reinterprt_cast'ing are very often Undefined Behavior. In most cases, you should use pointer or reference to std::byte (starting from C++17) if you want to achieve the bit representation of some data, it is almost always a legal operation. Other "safe" types are char and unsigned char, but I would say it shouldn't be used for that purpose in modern C++ as std::byte has better semantics.

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 has to work properly on big endian (e.g. some 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 write constexpr function: You can write a function to achieve this:

/*constexpr*/ bool is_little_endian() {
  std::uint16_t x=0x0001;
  auto p = reinterpret_cast<std::uint8_t*>(&x);
  return *p != 0;
}

Explanation: the binary representation of x in memory could be 0000'0000'0000'0001 (big) or 0000'0001'0000'0000 (little endian). After reinterpret-casting the byte under p pointer could be respectively 0000'0000 or 0000'0001. If you use static-casting, it will always be 0000'0001, no matter what endianness is being used.

EDIT:

In the first version I made example function is_little_endian to be constexpr. It compiles fine on the newest gcc (8.3.0) but the standard says it is illegal. The clang compiler refuses to compile it (which is correct).

trolzen
  • 119
  • 7
Mariusz Jaskółka
  • 4,137
  • 2
  • 21
  • 47
  • 4
    Nice example! I would replace short for uint16_t and unsigned char for uint8_t to make it less obscure for human. – Jan Turoň Aug 27 '18 at 09:41
  • 3
    @JanTuroň true, we can not assume that `short` takes 16 bits in memory. Corrected. – Mariusz Jaskółka Aug 28 '18 at 09:30
  • 3
    The example is wrong. reinterpret_cast is not allowed in constexpr functions – Michael Veksler Mar 02 '19 at 11:07
  • 1
    First of all, this code is rejected by both latest clang (7.0.0) and gcc (8.2.0). Unfortunately I did not find the limitation in formal language. All I could find was https://social.msdn.microsoft.com/Forums/vstudio/en-US/8937807a-5633-490c-9c94-b42dcd68a098/constexpr-allows-reinterpretcast-in-function-body?forum=vclanguage – Michael Veksler Mar 02 '19 at 16:03
  • Here is a better reference (with links to the standard): https://stackoverflow.com/a/26201529/4955498 – Michael Veksler Mar 03 '19 at 08:45
  • 3
    More specifically, https://en.cppreference.com/w/cpp/language/constant_expression (item 16) clearly states that reinterpret_cast can't be used in a constant expression. Also look at https://github.com/cplusplus/draft/blob/master/papers/N3797.pdf (5.19 constant expressions) pages125-126 which explicitly rules out reinterpret_cast. Then *7.1.5 The constexpr specifier* item 5 (page 146) *For a non-template, non-defaulted constexpr function ... if no argument values exist such that ... could be an evaluated subexpression of a core constant expression (5.19), **the program is ill-formed** * – Michael Veksler Mar 03 '19 at 09:18
  • There is never a reason to check endianness at runtime. Your example might misguide somebody into thinking that it's actually a good idea. – Daniel Kamil Kozar Oct 05 '19 at 09:05
  • @DanielKamilKozar explain your statement. There's even a new feature introduced for this purpose in C++20: https://en.cppreference.com/w/cpp/types/endian – Mariusz Jaskółka Dec 12 '19 at 13:49
  • @jaskmar It is simply not possible for the CPU to switch the endianness while executing code. Well, technically it is, but it won't do anybody any good : what happens to all the data and code in the RAM? Their endianness remains the same and won't magically change. "Bi-endian" CPUs have their endianness set early by initialisation code, and running actual code is only possible if the binary's endianness equals the CPU's endianness. [Have a read](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0463r1.html) of the original proposal - it explains a lot of this stuff. – Daniel Kamil Kozar Dec 13 '19 at 07:10
  • @DanielKamilKozar who says about switching it? We just sometimes need that (read-only) info. Especially if we compile one code to many different architectures. – Mariusz Jaskółka Dec 13 '19 at 07:29
  • Note that although casting something to char or (u)int8_t is allowed, casting the other way around is UB (f.eks. casting `uint8_t[2]` to `uint16_t`). – Mikhail Vasilyev Jun 09 '20 at 13:17
  • @jaskmar Regarding your Explanation part, how is it possible, that the result of static_cast will produce same results regardless of endianness? – ST Renegade Jul 29 '20 at 20:38
  • @STRenegade +1, I will be surprised that static_cast will give a different result than the reinterpret_cast example in the answer. I do think casting from `int*` to `float*` will show any differences neither. I like the solution of how to check endianness at runtime, but I think the explanation of reinterpret_cast is misleading. – Jeff Nov 25 '20 at 05:22
  • Legendary explanation. Somebody put that on a book. – gonidelis Jul 21 '22 at 17:38
21

The meaning of reinterpret_cast is not defined by the C++ standard. Hence, in theory a reinterpret_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 with reinterpret_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 use static_cast or some other alternative instead. Among other things the standard has this to say about what you can expect of static_cast (§5.2.9):

An rvalue of type “pointer to cv void” can be explicitly converted to a pointer to object type. A value of type pointer to object converted to “pointer to cv void” and back to the original pointer type will have its original value.

So for your use case, it seems fairly clear that the standardization committee intended for you to use static_cast.

flodin
  • 5,215
  • 4
  • 26
  • 39
  • 7
    Not quite crash your program. The standard offers a few guarantees about reinterpret_cast. Just not as many as people often expect. – jalf Feb 21 '09 at 16:43
  • 1
    Well, the reinterpret_cast itself would probably not crash, but it could return some bogus the result that, when you try to use it, could cause a crash. – flodin Feb 21 '09 at 16:56
  • 2
    Not if you use it properly. That is, reinterpret_cast from A to B to A is perfectly safe and well-defined. But the value of B is unspecified, and yes, if you rely on that, bad things could happen. But the cast itself is safe enough, as long as you only used it in the way the standard allows. ;) – jalf Feb 21 '09 at 19:10
  • 1
    reinterpret_crash<> will NOT crash your code. Other than that few guarantees. – Martin York Feb 21 '09 at 21:34
  • 61
    lol, I suspect that reinterpret_crash might indeed crash your program. But reinterpret_cast won't. ;) – jalf Feb 21 '09 at 21:35
  • 7
    I tried it on my compiler, and somehow, it refused to compile `reinterpret_crash`. No way a compiler bug will stop me from crashing my reinterpreting program. I'll report a bug ASAP! – paercebal Jul 11 '10 at 11:56
  • 20
    @paercebal `template T reinterpret_crash(U a) { return *(T*)nullptr; }` –  Jan 14 '12 at 10:41
11

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:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the deuce? 
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}

This was originally written in C, so uses C casts, but the analogous C++ cast is the reinterpret_cast.

Adam P. Goucher
  • 259
  • 2
  • 13
  • 1
    `error: invalid cast of an rvalue expression of type 'int64_t {aka long long int}' to type 'double&' reinterpret_cast((reinterpret_cast(d) >> 1) + (1L << 61))` - http://ideone.com/6S4ijc – Orwellophile Jul 10 '16 at 15:52
  • 3
    The standard says that this is undefined behavior: http://en.cppreference.com/w/cpp/language/reinterpret_cast (under "type aliasing") – Cris Luengo Mar 03 '17 at 18:40
  • @CrisLuengo If I substitute all `reinterpret_cast` with `memcpy`, is it still UB? – sandthorn Jul 16 '18 at 16:37
  • 1
    @sandthorn: This is UB according to the standard, but if it works for your architecture, don't worry about it. This trick is OK, I presume, for any compiler for Intel architectures. It could not work as intended (or even crash) on other architectures -- for example it could be possible that floats and longs are stored in separate memory compartments (not that I know of any such architecture, it's just an argument...). `memcpy` would definitely make it legal. – Cris Luengo Jul 16 '18 at 16:55
5

Here is a variant of Avi Ginsburg's program which clearly illustrates the property of reinterpret_cast mentioned by Chris Luengo, flodin, and cmdLP: that the compiler treats the pointed-to memory location as if it were an object of the new type:

#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

class A
{
public:
    int i;
};

class B : public A
{
public:
    virtual void f() {}
};

int main()
{
    string s;
    B b;
    b.i = 0;
    A* as = static_cast<A*>(&b);
    A* ar = reinterpret_cast<A*>(&b);
    B* c = reinterpret_cast<B*>(ar);
    
    cout << "as->i = " << hex << setfill('0')  << as->i << "\n";
    cout << "ar->i = " << ar->i << "\n";
    cout << "b.i   = " << b.i << "\n";
    cout << "c->i  = " << c->i << "\n";
    cout << "\n";
    cout << "&(as->i) = " << &(as->i) << "\n";
    cout << "&(ar->i) = " << &(ar->i) << "\n";
    cout << "&(b.i) = " << &(b.i) << "\n";
    cout << "&(c->i) = " << &(c->i) << "\n";
    cout << "\n";
    cout << "&b = " << &b << "\n";
    cout << "as = " << as << "\n";
    cout << "ar = " << ar << "\n";
    cout << "c  = " << c  << "\n";
    
    cout << "Press ENTER to exit.\n";
    getline(cin,s);
}

Which results in output like this:

as->i = 0
ar->i = 50ee64
b.i   = 0
c->i  = 0

&(as->i) = 00EFF978
&(ar->i) = 00EFF974
&(b.i)   = 00EFF978
&(c->i)  = 00EFF978

&b = 00EFF974
as = 00EFF978
ar = 00EFF974
c  = 00EFF974
Press ENTER to exit.

It can be seen that the B object is built in memory as B-specific data first, followed by the embedded A object. The static_cast correctly returns the address of the embedded A object, and the pointer created by static_cast correctly gives the value of the data field. The pointer generated by reinterpret_cast treats b's memory location as if it were a plain A object, and so when the pointer tries to get the data field it returns some B-specific data as if it were the contents of this field.

One use of reinterpret_cast is to convert a pointer to an unsigned integer (when pointers and unsigned integers are the same size):

int i; unsigned int u = reinterpret_cast<unsigned int>(&i);

Intrastellar Explorer
  • 3,005
  • 9
  • 52
  • 119
TRPh
  • 187
  • 1
  • 9
  • 2
    Everything here but the last example is undefined behavior; it’s interesting only as a (not reliable) means of illustrating implementation details of the language. – Davis Herring Aug 18 '20 at 14:30
3

You could use reinterprete_cast to check inheritance at compile time.
Look here: Using reinterpret_cast to check inheritance at compile time

Community
  • 1
  • 1
Martin R.
  • 67
  • 1
  • 4
1
template <class outType, class inType>
outType safe_cast(inType pointer)
{
    void* temp = static_cast<void*>(pointer);
    return static_cast<outType>(temp);
}

I tried to conclude and wrote a simple safe cast using templates. Note that this solution doesn't guarantee to cast pointers on a functions.

jwfearn
  • 28,781
  • 28
  • 95
  • 122
  • 2
    What? Why bother? This is precisely what `reinterpret_cast` already does in this situation: "An object pointer can be explicitly converted to an object pointer of a different type.[72] When a _prvalue_ `v` of object pointer type is converted to the object pointer type “pointer to _cv_ `T`”, the result is `static_cast(static_cast(v))`." -- N3797. – underscore_d Jan 07 '16 at 19:22
  • As for `c++2003` standard I can **NOT** find that `reinterpret_cast` does `static_cast(static_cast(v))` – Саша Зезюлинский Jan 12 '16 at 14:03
  • 1
    OK, true, but I don't care about a version from 13 years ago, and nor should most coders if (as is likely) they can avoid it. Answers and comments should really reflect the latest available Standard unless otherwise specified... IMHO. Anyway, I guess the Committee felt the need to explicitly add this after 2003. (because IIRC, it was the same in C++11) – underscore_d Jan 15 '16 at 22:48
  • Before `C++03` it was `C++98`. Tons of projects used old C++ instead of portable C. Sometimes you have to care about portability. For example you have to support the same code on Solaris, AIX, HPUX, Windows. Where it comes to compiler dependency and portability it is tricky. So a good example of introducing a portability hell is to use a `reinterpret_cast` in your code – Саша Зезюлинский Jan 16 '16 at 21:24
  • again, if like me you're happy to limit yourself only to platforms that play nice with the latest and greatest version of the language, your objection is a moot point. – underscore_d Jan 17 '16 at 00:10
  • Your `safe_cast` function does exactly the same what `reinterpret_cast` does: https://stackoverflow.com/a/68137312/5447906. – anton_rh Jun 26 '21 at 06:38
1

First you have some data in a specific type like int here:

int x = 0x7fffffff://==nan in binary representation

Then you want to access the same variable as an other type like float: You can decide between

float y = reinterpret_cast<float&>(x);

//this could only be used in cpp, looks like a function with template-parameters

or

float y = *(float*)&(x);

//this could be used in c and cpp

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:

#define asvar(x) ({decltype(x) __tmp__ = (x); __tmp__; })
cmdLP
  • 1,658
  • 9
  • 19
  • 1
    It is true that "it means that the same memory is used as a different type" but it is restricted to specific pair of types. In your example `reinterpret_cast` form `int` to `float&` is undefined behaviour. – Mariusz Jaskółka Dec 19 '19 at 08:16
  • Compilers optimize `memcpy` to purely register operations when possible; the casts are easy (but are also UB — if the value is *used* — as pointed out all over this page). – Davis Herring Aug 18 '20 at 14:32
-9

Quick answer: use static_cast if it compiles, otherwise resort to reinterpret_cast.

MD XF
  • 7,860
  • 7
  • 40
  • 71
Marius K
  • 498
  • 5
  • 6
-20

Read the FAQ! Holding C++ data in C can be risky.

In C++, a pointer to an object can be converted to void * without any casts. But it's not true the other way round. You'd need a static_cast to get the original pointer back.

MD XF
  • 7,860
  • 7
  • 40
  • 71
dirkgently
  • 108,024
  • 16
  • 131
  • 187