I have a value like this:
int64_t s_val = SOME_SIGNED_VALUE;
How can I get a
uint64_t u_val
that has exactly
I agree static_cast is appropriate in this case, but no one has mentioned a very similar looking case where static_cast wouldn't preserve bits as might be expected.
char x = -1; // 255
unsigned int x2 = static_cast<unsigned int>(x); // 4294967295
unsigned int x3 = static_cast<unsigned int>(static_cast<unsigned char>(x)); // 255
Watch out for sign extension when you are casting from a small signed value to a large unsigned value. Possibly other combinations are vulnerable too - I haven't thought it all the way through.
int64_t s_val = SOME_SIGNED_VALUE;
uint64_t u_val = static_cast<uint64_t>(s_val);
C++ Standard 4.7/2 states that:
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). ]
From the other hand, Standard says that "The mapping performed by reinterpret_cast
is implementation-defined. [Note: it might, or might not, produce a representation different from the original value. ]" (5.2.10/3). So, I'd recommend to use static_cast
.
Generally speaking, it doesn't matter whether you use static_cast<int64_t>
or reinterpret_cast<int64_t>
. So long as you are running on a processor that uses two's complement to represent negative numbers, the result is the same. (Practically all modern processors use that.) Under two's complement, a positive number in a signed int is represented the same way in an unsigned int; if it's a negative number it'll be reinterpreted as a large positive number in the unsigned form.
Basically, what your cast does is tell the compiler to produce different assembly instructions when dealing with that value. E.g. there are different instructions for multiplication and division for signed integers. Although addition and subtraction remains the same (read the wikipedia link and you'll understand).
Note that you don't need the cast at all. For all the wrangling about whether the cast will munge bits or not for negative representations, one thing has gotten lost - the cast is completely unnecessary.
Because of the conversions that C/C++ will do (and how casting is defined), this:
int64_t s_val = SOME_SIGNED_VALUE;
uint64_t u_val = s_val;
is exactly equivalent to:
int64_t s_val = SOME_SIGNED_VALUE;
uint64_t u_val = static_cast<uint64_t>(s_val);
That said, you might still want the cast because it signals intent. However, I've heard it argued that you shouldn't use unnecessary casts because it can silence the compiler in situations where you might want a warning.
Pick your poison.