To be excessively pedantic, that's not valid C or C++.
I suspect that every compiler in existence supports it, but as far as the standard is concerned, it's not valid to write one member of a union and then read another. However, to even know that float
and unsigned
are the same size you're already using some implementation-defined information, so you may as well use more. It's common and it generally works.
For reference, though, you can always examine memory as a series of bytes:
#include <iostream>
#include <iomanip>
#include <climits>
#include <cassert>
int main() {
float f = 0.3;
unsigned char *buf = (unsigned char*)(&f);
// Now we just have to print the sucker.
assert(CHAR_BIT == 8); // otherwise hex isn't much use
// This shows the byte representation, low addresses on the left.
// On a little-endian machine, you might like to count down for
// convenience of reading.
for (int i = 0; i < sizeof f; ++i) {
std::cout << std::hex << std::setw(2) << std::setfill('0');
std::cout << static_cast<unsigned int>(buf[i]) << ' ';
}
std::cout << '\n';
}
Output (on my machine):
9a 99 99 3e
If you do prefer to use unsigned
rather than unsigned char
:
#include <cstring>
float f = 0.3;
unsigned u;
assert(sizeof f == sizeof u);
std::memcpy(&u, &f, sizeof f);
std::cout << std::hex << u << "\n";
Output (on my machine):
3e99999a