Union not reinterpreting values?

This is only affecting the last half of the mantissa. It won't make any noticeable difference with the amount of digits you're printing. However, the difference can be seen when you print 64 digits.

This program will show the difference:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

union myUnion
{
    int x;
    long double y;
};

int main()
{
    union myUnion a;
    a.y = 3.2;
    a.x = 5;
    printf("%d\n%.64Lf\n", a.x, a.y);
    a.y = 3.2;
    printf("%.64Lf\n", a.y);
    return 0;
}

My output:

5
3.1999999992549419413918193599855044340074528008699417114257812500
3.2000000000000001776356839400250464677810668945312500000000000000

Based on my knowledge of the 80-bit long double format, this overwrites half of the mantissa, which doesn't skew the result much, so this prints somewhat accurate results.

If you had done this in my program:

a.x = 0;

the result would've been:

0
3.1999999992549419403076171875000000000000000000000000000000000000
3.2000000000000001776356839400250464677810668945312500000000000000

which is only slightly different.


The size of long double is very large. To see the effect of modifying the x field on implementations where x lines up with the LSBs of the mantissa of y and other bits of union are not effected when modifying via x, you need to print the value with much higher precision.


However, the reverse doesn't really apply

On a little endian system (least significant byte of a multi-byte value is at the lowest address), the int will correspond to the least significant bits of the mantissa of the long double. You have to print that long double with a great deal of precision to see the effect of that int on those insignificant digits.

On a big endian system, like a Power PC box, things would be different: the int part would line up with the most significant part of the long double, overlapping with the sign bit, exponent and most significant mantissa bits. Thus changes in x would have drastic effects on the observed floating-point value, even if only a few significant digits are printed. However, for small values of x, the value appears to be zero.

On a PPC64 system, the following version of the program:

int main(void)
{
    union myUnion a;
    a.y = 3.2;
    int i;
    for (i = 0; i < 1000; i++) {
      a.x = i;
      printf("%d -- %.2Lf\n", a.x, a.y);
    }
    return 0;
}

prints nothing but

1 -- 0.0
2 -- 0.0
[...]
999 - 0.0

This is because we're creating an exponent field with all zeros, giving rise to values close to zero. However, the initial value 3.2 is completely clobbered; it doesn't just have its least significant bits ruffled.