Why can't I use reinterpret_cast uint for int?

Here is what I want to do:

const int64_t randomIntNumber = reinterpret_cast<int64_t> (randomUintNumber);

If randomUintNumber is of type uint64_t .

Error (MSVC 2010):

error C2440: 'reinterpret_cast': cannot convert from 'const uint64_t' to 'int64_t' 1> Conversion is a valid standard conversion that can be done implicitly or using static_cast, C-style cast or functional style

Why doesn't it compile? both types have the same bit length, why reinterpret_cast is not for what?

+6
source share
6 answers

Because this is not what reinterpret_cast . All permitted conversions with reinterpret_cast include pointers or references, except that the integer or enum type can be reinterpret_cast for itself. All of this is defined in the standard, [expr.reinterpret.cast] .

I'm not sure what you are trying to achieve here, but if you want randomIntNumber have the same meaning as randomUintNumber , then do

 const int64_t randomIntNumber = randomUintNumber; 

If this leads to a compiler warning, or if you just want to be more explicit, then:

 const int64_t randomIntNumber = static_cast<int64_t>(randomUintNumber); 

The result of the cast has the same meaning as the input if randomUintNumber less than 2 63 . Otherwise, the result will be determined by the implementation, but I expect all known implementations that int64_t will define it to do the obvious thing: the result is equivalent to input modulo 2 64 .


If you want randomIntNumber have the same bit pattern as randomUintNumber , you can do this:

 int64_t tmp; std::memcpy(&tmp, &randomUintNumber, sizeof(tmp)); const int64_t randomIntNumber = tmp; 

Since int64_t guaranteed to use two additional representations, you hope that the implementation defines static_cast to have the same result as for values ​​outside the uint64_t range. But in fact, this is not guaranteed in the AFAIK standard.

Even if randomUintNumber is a compile-time constant, unfortunately, here randomIntNumber not a compile-time constant. But then, how is “random” a compile-time constant ?; -)

If you need to get around this, and you don't trust the implementation, to be reasonable about converting non-standard unsigned values ​​to signed types, then something like this:

 const int64_t randomIntNumber = randomUintNumber <= INT64_MAX ? (int64_t) randomUintNumber : (int64_t) (randomUintNumber - INT64_MAX - 1) + INT64_MIN; 

Now I advocate writing truly portable code wherever possible, but even so, I think it borders on paranoia.


Btw, you may be tempted to write the following:

 const int64_t randomIntNumber = reinterpret_cast<int64_t&>(randomUintNumber); 

or equivalently:

 const int64_t randomIntNumber = *reinterpret_cast<int64_t*>(&randomUintNumber); 

This is not entirely guaranteed to work, because although they exist where int64_t and uint64_t , it is guaranteed that they are a signed type and an unsigned type of the same size, in fact they are not guaranteed to be signed and unsigned versions of the standard integer type. Thus, this is implementation-specific, regardless of whether this code violates a strict alias. Code that violates a strict alias has undefined behavior. The following does not violate a strict alias, and this is normal if the pattern bit in randomUintNumber is a valid representation of the long long value:

 unsigned long long x = 0; const long long y = reinterpret_cast<long long &>(x); 

So, in implementations where int64_t and uint64_t are typedefs for long long and unsigned long long , then my reinterpret_cast is fine. And just as with converting values ​​out of range to fit the implementation, you should expect that a reasonable thing to implement is to make them the corresponding types with / without signature. So, like static_cast and implicit conversion, you expect it to work in any reasonable implementation, but in reality it is not guaranteed.

+19
source

No, it is not. reinterpret_cast is mainly intended to re-interpret the existing storage bit as a different type than it is. Many of these interpretations are implementation-specific, and the standard lists a specific (fairly long to indicate here) list of things that can be done with reinterpret_cast (mainly to distinguish between different types of pointers / references), but says:

No other conversion can be performed explicitly using reinterpret_cast.

In your case, you probably want to convert the types, not reinterpret the existing repository. Use static_cast for this purpose.

+3
source

Use static_cast in these cases. I believe that the language developers, in all their wisdom, decided that this was not considered "dangerous enough" to guarantee reinterpret_cast .

+2
source

From C ++ 11 Standard (N3376) 5.2.10.1:

The following are conversions that can be performed explicitly using reinterpret_cast. no other conversion can be performed explicitly using reinterpret_cast.

A single conversion from an integral type to an integrated type is allowed if the types are identical.

Others include pointers.

+1
source

reinterpret_cast used to reinterpret the storage of an object as another object. If you do not want to go through the standard wording, you can find everything reinterpret_cast can do here . Typically, you can remember that you need to work with pointer types.

So, if you really want to rethink the bits used for your uint64_t as int64_t , follow these steps:

 int64_t randomIntNumber = reinterpret_cast<int64_t&> (randomUintNumber); 

However, if you just want to transform the object, preserving its value, if possible ... just do what the compiler offers and use static_cast .

+1
source

Why doesn't it compile?

Because none of them is a pointer.

both types have the same bit length,

Why is this important? If they were pointers, it might be important that they point to things of the same size, but they are not pointers.

what is reinterpret_cast for?

No, reinterpret_cast to cast the pointer. You could do what you want by placing & inside the actor and * outside of him. This is what you need for reinterpretation.

0
source

All Articles