0
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
    //from float to bits
    float f;
    cin >> f;
    int x = *(int*)&f;
    cout << x << "\n";
    bitset<sizeof(int) * 8> binary(x);
    cout << binary;
}

What does the *(int*)& do that makes bitset work?

I can understand that &f makes it the address and x= sizeof address f? (maybe) but how does it work in bitset<sizeof(int)> and what does the * 8 do?

Vadim Chernetsov
  • 370
  • 1
  • 2
  • 14
  • 10
    Note that `int x = *(int*)&f;` is [a strict aliasing violation](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) and undefined behavior. – Andrew Henle Nov 26 '21 at 15:17
  • out of curiosity, where did you find that code? – 463035818_is_not_an_ai Nov 26 '21 at 15:20
  • This is actually an old C hack. `float` and `int` may have the same size (may but not must). `*(int*)&f` is a "reinterprete" cast. It re-interpretes the storage of `float f` as it was an `int`. With `int` the bit arithmetic can be applied to evaluate / isolate the bits. Nevertheless - it's an old C hack and not valid anymore in C++. (I'm even not sure whether this is still allowed in modern C.) – Scheff's Cat Nov 26 '21 at 15:23
  • `sizeof(int) * 8` multiplies the size of `int` with 8 to obtain the number of bits. (`sizeof` returns the number in Bytes.) – Scheff's Cat Nov 26 '21 at 15:24
  • 2
    The C++ equivalent is using `std::memcpy` to copy the bits from the `float` into an `int`. – Eljay Nov 26 '21 at 15:24
  • do you want to get explained how you can examine the bits of a `float` or do you want to get this particular code explained? Thats quite different questions, because the code is not valid C++ – 463035818_is_not_an_ai Nov 26 '21 at 15:25
  • I actually wanted to know how to change float to bits through this code but quickly understood that this code is invalid – shiraori Nov 26 '21 at 16:16
  • `f` is a `float`. `x = *(int *)&f` has undefined behaviour (strict aliasing violation). With a lot of compilers, if `int` and `float` have the same type, it has the effect of producing an `int` with the same bit-wise representation as `f`. – Peter Nov 26 '21 at 22:27

1 Answers1

4

What does the *(int*)& do that makes bitset work?

That's a sequence of three unary operators, *, (int *), and &. As used in the code presented, *(int*)&f first computes a pointer to f (of type float *), then the C-style cast converts that to type int *, and finally the * dereferences that to get a value of type int. Overall, this ...

int x = *(int*)&f;

... is roughly equivalent to ...

int x = reinterpret_cast<int&>(f);

... including that both elicit undefined behavior. But the intention is that the representation of f's value is interpreted as an int.

how it have any relations to the bitset?

std::bitset has a constructor that accepts an integer argument, which initializes the bitset from the bits of the argument's value. There is no such constructor that accepts a float, and a normal value conversion from type float to type int does not preserve the bit pattern of the float.

It would be better to use a union to perform such a conversion:

union { float f; int x; } u;

cin >> u.f;
cout << u.x << "\n";
bitset<sizeof(int) * 8> binary(u.x);
cout << binary;

In C, you could use a union for that, but in C++, you need another solution, such as memcpy():

float f;
int x;

cin >> f;
memcpy(&x, &f, sizeof(x));
cout << x << "\n";
bitset<sizeof(int) * 8> binary(x);
cout << binary;
John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • 2
    Isn't type punning with unions in C++ prohibited as well? (in opposition to C where it's still allowed with certain (reasonable) constraints) I believe as well (like mentioned in one of the comments), the correct way would be to use a `memcpy()` or, maybe, using a cast to `char*`. – Scheff's Cat Nov 26 '21 at 15:34
  • 1
    You're right, @Scheff'sCat. Answer revised. – John Bollinger Nov 26 '21 at 15:39