#include <stdio.h>
union data {
int a;
float b;
};
int main()
{
union data a1;
a1.a=4;
printf("%d \n%f", a1.a, a1.b);
return 0;
}
Why does this output 4 and 0.000000? I would expect it to be 4 and 4.0.
#include <stdio.h>
union data {
int a;
float b;
};
int main()
{
union data a1;
a1.a=4;
printf("%d \n%f", a1.a, a1.b);
return 0;
}
Why does this output 4 and 0.000000? I would expect it to be 4 and 4.0.
Floating point numbers and integers do not have the same representation, so the same sequence of bytes have different values for the two types.
Integers are typically stored as a sequence of bits. So assuming an integer is 4 bytes, the integer value 4 looks like 00000000 00000000 00000000 00000100
in binary.
Floating point types on the other hand are represented completely differently. Most implementations use IEEE754 format. For a single-precision floating point number, which is what a float
typically is, the first bit is the sign bit, the next 8 bits are the base-2 exponent minus 127, and the last 23 bits are the binary significand (with an implicit leading 1).
So the number 4.0 in this format would look like this in binary:
01000000 10000000 00000000 00000000
Which split into its components is:
0 10000001 00000000000000000000000
Here, the sign bit is 0 so the number is positive. The value in the exponent field is 129 which translates to 2. The significant field is 00000000000000000000000, which with the implicit leading 1 is 1.00000000000000000000000. So the value is + 1.0 x 22, i.e. 4.
If you took the integer representation of 4 and tried to interpret it as a float
, this is what would happen:
Starting with the binary representation of 4 as a int
:
00000000 00000000 00000000 00000100
Now we treat it as a float
and break up the fields:
0 00000000 00000000000000000000100
The sign bit is 0 so we have a positive value. An exponent value of 0 is a special flag for a denormal number. This means the exponent is understood to be -126 and the significant has a leading 0 instead of a leading 1. So the significant value with the implicit leading 0 is 0.00000000000000000000100. This gives us a value of + 0.000000000000000000001 x 2-126, or + 1.0 x 2-147, which is roughly 5.605194 x 10-45 in decimal. This value is below the 6 significant digit default used by the %f
format specifier so 0.000000 is printed.
Remember that in a union, all members occupy the same storage - a
and b
occupy the same bytes. Writing to a
overwrites b
and vice-versa.
The binary representations of int
and float
are wildly different from each other. Assuming 4-byte big-endian for both and IEEE-754 floating-point format, then we have
Value Binary Representation
----- ---------------------
4 00000000 00000000 00000000 00000100
4.0 01000000 10000000 00000000 00000000
I won't go into the specifics of the IEEE-754 format, but basically the binary representation of the integer value 4 corresponds to a floating-point value that's practically 0 (out to 6 decimal places, at least), which explains your output. Similarly, the binary representation of the floating-point value 4.0 corresponds to a very large integer.