-3
#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.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
Mbappe
  • 13
  • 4
    Please post code, errors, sample data or textual output here as plain-text, not as images that can be hard to read, can’t be copy-pasted to help test code or use in answers, and are hostile to those who use screen readers. You can edit your question to add the code in the body of your question. Use the `{}` button to format any blocks of code, or indent with four spaces for the same effect. **Unfortunately, we can’t run your screenshot as code.** – tadman Jul 20 '18 at 17:53
  • 1
    `data.a` and `data.b` occupy the exact same spot in memory. You can use one or the other but not both. If you need both values to persist properly you should use a `struct`. – tadman Jul 20 '18 at 17:53
  • @Yunnosch but In union, all members share the same memory location.so floating data type b should contain the integer type a value?? – Mbappe Jul 20 '18 at 17:57
  • @Mbappe Because a `float` and an `int` have different representation, i.e. the way they're laid out is not the same. – dbush Jul 20 '18 at 17:59
  • How do you imagine the four byte values of a float (asuming size 4) which does contain 4.0? – Yunnosch Jul 20 '18 at 18:00
  • @dbush so can you please justify how the answer is 0.000 in the case of floating number? – Mbappe Jul 20 '18 at 18:00
  • Some light reading on floating point number representation: https://en.wikipedia.org/wiki/IEEE_754 – Christian Gibbons Jul 20 '18 at 18:01
  • Not a dupe but probably helpful/interesting https://stackoverflow.com/questions/47430607/is-it-safe-to-detect-endianess-with-union/47430774#47430774 – Yunnosch Jul 20 '18 at 18:02
  • Did you try try the opposite? Write 4.0 into `b` and then print `a` in hex. – Yunnosch Jul 20 '18 at 18:06
  • @Yunnosch yes in that case the output is 1191182336 for int and 32768.000000 for float.. as i think for input 32768 overflow will be in int. – Mbappe Jul 20 '18 at 18:09
  • 3
    Could you please remove that picture and show code in text shape? I would so like to to keep this in my dupe library, but with a picture of code I can't... – Yunnosch Jul 20 '18 at 18:34
  • @Yunnosch Took care of it. – dbush Jul 20 '18 at 18:45
  • @dbush So selfless of you. (yes, there is a little sarcasm, but in total it is an honest compliment for your effort on this) – Yunnosch Jul 20 '18 at 18:46

2 Answers2

3

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.

dbush
  • 205,898
  • 23
  • 218
  • 273
0

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.

John Bode
  • 119,563
  • 19
  • 122
  • 198