Let's make a minor change to the code:
#include <iostream>
int main() {
double a = 5.0;
double *d = &a;
char *b = (char *)&a;
int a1 = 10;
for (int i = 0; i < sizeof(double); i++)
std::cout << std::hex << (int)b[i] << "\t";
}
This shows us the individual bytes of the double
as they're stored in memory. The result I get is:
0 0 0 0 0 0 14 40
Now, if you look at the first four bytes of this, they're all zeros. Assuming your int
is two or four bytes, when you try to view that memory as an int
, the result is going to be zero, because all the non-zero bytes of the double are stored later in memory than the part you're looking at when using it as an int
.
Of course, if you printed it out as a long long int
instead, you'd get a non-zero result (a long long int
is required to be at least 64 bits). Likewise, if you were doing this on a big-endian system, the 14
and 40
bytes of the double
would probably be stored at the first bytes in memory rather than the last, so the result would again be non-zero.
The bottom line is that in this case, your cast is roughly equivalent to a reinterpret_cast
. Rather than taking the double
value and converting it to an int
value, it's looking at the bytes of memory occupied by the double
, and interpreting them as if they were an int
.
Note that the result above isn't really required and you can't count on its happening in portable code. It is quite common and widely expected though (e.g., on most little-endian machines with IEEE floating point and 32-bit int
s).