How can I print a C double bit-by-bit to see the low-level representation?
I want to learn how the computer represents the double
type in bit, but the &
and |
bit operators can't use double
. And memcpy(&d, &src, 8)
also doesn't seem to wo开发者_如何学编程rk. Any suggestions?
Here:
#include <stdio.h>
int main ()
{
double decker = 1.0;
unsigned char * desmond = (unsigned char *) & decker;
int i;
for (i = 0; i < sizeof (double); i++) {
printf ("%02X ", desmond[i]);
}
printf ("\n");
return 0;
}
You can try it: http://codepad.org/onHnAcnC
union {
double d;
unsigned char c[sizeof(double)];
} d;
int main(int ac, char **av) {
int i;
char s1[80], s2[80];
d.d = 1.0;
for(i = 0; i < sizeof d; ++i) {
sprintf(s1 + i * 3, " %02x", d.c[i]);
sprintf(s2 + i * 3, " %02x", d.c[sizeof d - 1 - i]);
}
printf("%s\n%s\n", s1, s2);
return 0;
}
$ ./a.out
00 00 00 00 00 00 f0 3f
3f f0 00 00 00 00 00 00
Or you could just read about the IEEE 754 standard, which specifies representation.
http://en.wikipedia.org/wiki/IEEE_754-1985
A particular bit layout by itself is meaningless. Suppose I have the following: 1101
Maybe I say that is unsigned and it represents the value 13.
Maybe it is signed and that high bit signifies that the value is a negative which means it is now -5.
Consider further that I consider the high two bits to be a base and the low two bits to be an exponent, then I get the value 3.
You see, it isnt the storage, its the interpretation. Read up on how floating point values are represented and interpreted; it will serve you much better than seeing how the bits are packed.
That isn't going to be very enlightening unless you also know a bit about typical IEEE FP representations.
Most likely the way your machine represents doubles is spelled out here.
This works for me
#include <stdio.h>
#include <string.h> /* memmove */
int main(void) {
unsigned char dontdothis[sizeof (double)];
double x = 62.42;
printf("%f\n", x);
memmove(&dontdothis, &x, sizeof dontdothis);
/* examine/change the array dontdothis */
dontdothis[sizeof x - 1] ^= 0x80;
/* examine/change the array dontdothis */
memmove(&x, &dontdothis, sizeof dontdothis);
printf("%f\n", x);
return 0;
}
The result is
62.420000
-62.420000
The key is to convert the double
to a long long
(assuming sizeof(double) == sizeof(long long)
) without changing binary representation. This can be achieved by one of the following methods:
- cast:
double a; long long b = *((long long *)&a);
- union:
union { double a ; long long b };
Another option is to use bitfields. Armed with such a structure and knowledge of how a double is supposed to be stored on your computer you can very easily print out the different parts of the internal representation of the double. A bit like they do here.
精彩评论