Reinterpret cast from float to int

reinterpret_cast
reinterpret_cast void*
reinterpret_cast vs static_cast
dynamic_cast
when to use reinterpret_cast
c++ reinterpret_cast<float to int
reinterpret_cast vs c cast
c++ cast double to int
float f = 12.5;
unsigned int _f = *reinterpret_cast<int*>(&f);
std::cout << _f << std::endl; // result: 1095237632

Can some explain me how such casting works? And what is represented by _f?

EDIT So this number I got 1095237632 after converting to binary is 0b1000001010010000000000000000000 and this binary number is 12.5 in IEEE-754. Do I get it right?

Let's look at two functions. One of them casts float to int it regularly, and one of them reinterpret casts it using reinterpret_cast:

int cast_to_int(float f) {
    // Rounds f to an int, rounding towards 0
    return (int)f; 
}
int reinterpret_cast_to_int(float i) {
    // Just copies the bits
    return *reinterpret_cast<int*>(&i); 
}

So what actually happens? Let's look at the assembly:

cast_to_int(float):
    cvttss2si       eax, xmm0   // We cast to an int
    ret
reinterpret_cast_to_int(float):
    movd    eax, xmm0           // We directly copy the bits
    ret

In the first case, there's an assembly instruction that performs the conversion:

cast_to_int(0.7) -> 0
cast_to_int(1.0) -> 1
cast_to_int(1.5) -> 1
cast_to_int(2.1) -> 2

In the second case, reinterpret_cast just directly transforms the underlying representation of the bits. It's not actually doing anything, and the function just copyies the input register to the output register.

Under the hood, floats have a very different bit representation than ints, and that's why you're getting weird numbers.

reinterpret_cast conversion, This can include a static cast , a const cast or a reinterpret cast (the latter two of convert an int to a float so we get floating point division rather than integer� static_cast<T&&>(*reinterpret_cast<T*>(&(x))) Reinterpreting one type of pointer as an incompatible type of pointer is usually invalid. The reinterpret_cast operator, as well as the other named cast operators, is more easily spotted than C-style casts, and highlights the paradox of a strongly typed language that allows explicit casts.

Nobody can explain (*), because it does not work.

From cppreference:

Unlike static_cast, but like const_cast, the reinterpret_cast expression does not compile to any CPU instructions (except when converting between integers and pointers or on obscure architectures where pointer representation depends on its type). It is purely a compile-time directive which instructs the compiler to treat expression as if it had the type new_type.

Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility.

And then follows a list of rules covering what reinterpret casts are allowed. Casting type A to a completely unrelated type B is not among them and your code exhibits undefined behaviour.

(*) Strictly speaking not true. You are treating a float as an int and if you look at their representation on your hardware and if you inspect the output of your compiler you can work out why you get the value you get, though undefined behaviour is undefined and its not worth entering details unless you are willing to write nonportable code.

6.16 — Explicit type conversion (casting) and static_cast, Converting to int from some smaller integer type, or to double from float is known as Type-cast operator: allow implicit conversion to a particular type. Returns a value of type new_type. [] ExplanatioUnlike static_cast, but like const_cast, the reinterpret_cast expression does not compile to any CPU instructions (except when converting between integers and pointers or on obscure architectures where pointer representation depends on its type).

As the comments below say, the usage of reinterpret_cast ist not safe for unrelated types. So don't use it this way.

First, assigning int to uint should be avoided.

For x86/x64 systemns, float is usually represented as 4 bytes, like uint32_t, and they have mostely the same alignment.

Many compilers allow the following: uint32_t _f = *reinterpret_cast(&f);

But this leads to undefined behavior due to some reasons (thanks for the comments): - optimizations - alignment - ...

Use memcpy instead.

If alignment is the same and the values are stored in memory, the following effect desribes what happens when used reinterpret_cast:

The memory location of the 4 bytes float is &f. With a reinterpret cast to uint32_t, this memory is reinterpretet as an uint32. The dereferenced value _f contains the same bytes as the float f, but interpreted as uint32. You could cast it back and get the original value 12.5:

float f = 12.5;
uint32_t _f = *reinterpret_cast<uint32_t*>(&f);
float _fnew = *reinterpret_cast<float*>(&_f);
std::cout << _fnew << std::endl; // result: 12.5

reinterpret_cast only reinterpretes memory locations (addresses). If the alignment is not the same or the values are stored in registers, are optimized an so on, the cast can lead to undefined values.

Type conversions - C++ Tutorials, It is used to convert one pointer of another pointer of any type, no matter / 573294/when-to-use-reinterpret-cast” rel=”noopener” target=”_blank reinterpret_cast reinterpret_cast converts any pointer type to any other pointer type, even of unrelated classes. The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked. It can also cast pointers to or from

reinterpret_cast in C++, Type errors can also be introduced by explicit conversions, or casts, in the Any conversion from a floating point type to an integral type is a� Reinterpret Cast Static Cast: This is the simplest type of cast which can be used. It is a compile time cast.It does things like implicit conversions between types (such as int to float, or pointer to void*), and it can also call explicit conversion functions (or implicit ones).

Type conversions and type safety, Unspecified behavio / Result of some reinterpret cast conversions / Essential C++ . int x = 42; char* p = reinterpret_cast<char*>(&x); // p has unspecified value. However, with most compilers, this 5 Floating point arithmetic. 6 Bit operators. In the above program, we use a float C-style cast to tell the compiler to convert i1 to a floating point value. Because the left operand of operator/ now evaluates to a floating point value, the right operator will be converted to a floating point value as well, and the division will be done using floating point division instead of integer division!

Unspecified behavio / Result of some reinterpret cast conversions , T->T is allowed per [expr.reinterpret.cast]p2 so long as it doesn't // cast away void pointer_conversion() { int p1 = 0; float p2 = reinterpret_cast (p1); structure p3 � When casting from a float to an int, the value is truncated not rounded. So both (int) 3.2 and (int) 3.7 are 3.

Comments
  • "what is represented by _f?" Nothing. You get undefined behavior. Look that term up.
  • You might also be interested by the physical representation of IEEE-754, look that up.
  • casting did not mean conversion! any data has a representation in memory. cast tells the compiler to use the given representation as a different type. float and int have not a common representation and the cast is invalid
  • For complex types, the behaviour would be undefined. For primitive types of same size, there are reasons to do such things and the behaviour is well defined.
  • @AntonF. I dont understand what you mean, even if float and int are of same size, reinterpreting a float* as an int* would be wrong (well actually float* and int* are of same size)
  • So this number I got 1095237632 after converting to binary is 0b1000001010010000000000000000000 and this binary number is 12.5 in IEEE-754. Do I get it right?
  • @irezwi you can check it eg here
  • "float is represented as 4 bytes in memory." not necessarily. And the behaviour of your code is undefined.
  • "Assign to int should be avoided" is misleading. float x = 3.5; int y = x; is completely fine if thats what you want to do
  • @user463035818 If you want to reinterprete the value and not to get the casted value for some reasons, my answer seems correct to me and explains what was asked ("how such casting works").
  • @Bathsheba In general, you're right. I assumed x86/x64 systems (I edited my answer therefore). In a more general case, you could statically assert the size of float. Then the behaviour is well defined.
  • "Seems correct to me". It explicitly is not allowed by the standard. I'm not sure what more can be said?