unsigned
is just short for unsigned int
and using C++-style casts the line would translate to
unsigned int u = *reinterpret_cast<unsigned int*>(&x);
However read below why this causes undefined behavior in either case.
(I recommend to not use C-style casts as in the line shown in the question, since it is not obvious to which C++-style cast they resolve.)
If x
is a float
variable, then the line is trying to reinterpret the object representation of the float
variable as the object representation of an unsigned int
, basically to reinterpret the float
's memory as the memory of an unsigned int
, and then stores the unsigned int
value corresponding to that representation in u
.
Step for step, &x
is a pointer to x
of type float*
, reinterpret_cast<unsigned int*>(&x)
is a pointer to x
, but now of type unsigned int*
. And then *reinterpret_cast<unsigned int*>(&x)
is supposed to dereference that unsigned int*
pointer to the float
variable to retrieve an unsigned int
value from the pointed-to memory location as if the bytes stored there represented an unsigned int
value instead of a float
value. Finally unsigned int u =
is supposed to use that value to initialize u
with it.
That causes undefined behavior because it is an aliasing violation to access a float
object through a unsigned int*
pointer. Some compilers have options which can be enabled to allow this (under the assumption that float
and unsigned int
have compatible size and alignment), but it is not permitted by the standard C++ language itself.
Generally, whenever you see reinterpret_cast
(or a C-style cast that might resolve to a reinterpret_cast
), you are likely to cause undefined behavior if you don't know exactly what you are doing.
Since C++20 the correct way to do this without undefined behavior is using std::bit_cast
:
float x = /*...*/;
auto u = std::bit_cast<unsigned>(x);
or before C++20 using std::memcpy
:
float x = /*...*/;
unsigned u;
static_assert(sizeof(u) == sizeof(x));
std::memcpy(&u, &x, sizeof(u));
The size verification is done by std::bit_cast
automatically. Even without C++20 it would probably be a good idea to wrap the static_assert
and memcpy
in a similar generic function for reuse.
Both of these still require that the representation of x
is also a valid representation for a u
. Otherwise the behavior is still undefined. I don't know whether there even is any C++ implementation where this doesn't hold for all values in the float -> unsigned
case.
Also as an additional note: C is a different language. The rules may well be different in C. For example there is obviously no reinterpret_cast
in C to which the (unsigned*)
cast could resolve and the object model is very different. In this case though, C's aliasing rules will have an equivalent effect.