>It outputs 0 when I would expect 2.
The problem is with your expectation. You're punning the bytes of a multi-byte object(float) to raw binary, then casting the first byte of the result to another multi-byte type (int) and somehow expecting the value to match what was originally stored in the original multi-byte object. This is ignoring the non-trivial byte representation of floating-point that doesn't map well to integers in a direct conversion.
Might I suggest inspecting the bytes directly instead?
using namespace std;
float f = 2;
// Pun to raw binary
unsigned char* c = reinterpret_cast<unsigned char*>(&f);
// Display the byte representation of f
for (size_t i = 0; i < sizeof(float); i++)
cout<< bitset<numeric_limits<unsigned char>::digits>(c[i]) <<' ';
// Do a round trip back to float
std::cout<< *reinterpret_cast<float*>(c) << '\n';
 An array or pointer to unsigned char is as close as you get in C++.
 Note that the "first" byte depends on the endianness of the representation.