It seems to me you don't quite understand what a union is. The members of a union are overlapping values (in other words, the three members of a Count
union share the same space).
Assuming, just for the sake of demonstration, a short
is 16 bits (2 bytes), a float
is 32 bits (4 bytes) and a double
is 64 bits (8 bytes), then the union is 8 bytes in size. In little-endian format, the num
member refers to the first 2 bytes, the weight
member refers to the first 4 bytes (including the 2 bytes of num
) and the volume member refers to the full 8 bytes (including the 2 bytes of num
and the four bytes of weight
).
Initially, your union contains garbage, i.e. some unknown bit pattern, let's display it like this (in hex):
GG GG GG GG GG GG GG GG // GG stands for garbage, i.e. unknown bit patterns
If you set num
to 2, then the first two bytes are 0x02
0x00
, but the other bytes are still garbage:
02 00 GG GG GG GG GG GG
If you read weight
, you are simply reading the first four bytes, interpreted as a float
, so the float
contains the bytes
02 00 GG GG
Since floating point values have a totally different format as integral types like short
, you can't predict what those bytes (i.e. that particular bit pattern) represent. They do not represent the floating point value 2.0f, which is what you probably want. Actually, the "more significant" part of a float
is stored in the upper bytes, i.e. in the "garbage" part of weight
, so it can be almost anything, including a NaN
, +infinity
, -infinity
, etc.
Similarly, if you read volume
, you have a double
that consists of the bytes
02 00 GG GG GG GG GG GG
and that does not necessarily represent 2.0 either (although, by chance, it MAY come very close, if by coincidence the right bits are set at the right places, and if the low bits are rounded away when you display such a value).
Unions are not meant to do a proper conversion from int
to float
or double
. They are merely meant to be able to store different kinds of values to the same type, and reading from another member as you set simply means you are reinterpreting a number of bits that are present in the union as something completely different. You are not converting.
So how do you convert? It is quite simple and does not require a union:
short num = 2;
float weight = num; // the compiler inserts code that performs a conversion to float
double volume = num; // the compiler inserts code that performs a conversion to double