Captain_Obvious Captain_Obvious - 1 month ago 13
C Question

Two doubles with bits copied differently from a long are printed differently

As shown in the code below, I am trying to copy the bits from a long

longnum
to two doubles,
d1
and
d2
, using different methods: pointer-casting + dereferencing and 'bitwise-and'ing respectively.

# include <stdio.h>

int main(void) {
long longnum = 0xDDDDDDDDDDDDDDDD;
double d1 = *((double*)(&longnum));
double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

printf("%ld\n\n",longnum);
printf("%lf\n\n",d1);
printf("%lf\n",d2);
return 0;
}


The issue is that both the doubles are not printed the same way, as shown in the output below.

-2459565876494606883

-1456815990147462891125136942359339382185244158826619267593931664968442323048246672764155341958241671875972237215762610409185128240974392406835200.000000

15987178197214945280.000000


Given the size of
DBL_MAX
, the max size of a double, it seems to me that it's the giant number that's actually the sensible output of the two doubles printed.

Answer
double d2 = longnum & 0xFFFFFFFFFFFFFFFF;

The & mask doesn't do anything. A number ANDed with all 1's is the same number. The line above is no different from:

double d2 = longnum;

That line doesn't do any bit reinterpretation. Instead it sets d2 to the double that most closely represents the value in longnum. The value will be similar; the bit pattern will be quite different.

The best way to do what you're trying to do is with a union. Unions are the best way to perform type punning.

union {
     long l;
     double d;
} u;

u.l = longnum;
printf("%f\n\n", u.d);

Using pointers as you did with d1 technically invokes undefined behavior. It is a common idiom and in practice will probably work fine, but type punning with pointers ought to be avoided.