8

Suppose I define a union like this:

#include <stdio.h>

int main() {
    union u {
        int i;
        float f;
    };
    union u tst;
    tst.f = 23.45;

    printf("%d\n", tst.i);

    return 0;
}

Can somebody tell me what the memory where tst is stored will look like?

I am trying to understand the output 1102813594 that this program produces.

timrau
  • 22,578
  • 4
  • 51
  • 64
Moeb
  • 10,527
  • 31
  • 84
  • 110

5 Answers5

11

It depends on the implementation (compiler, OS, etc.) but you can use the debugger to actually see the memory contents if you want.

For example, in my MSVC 2008:

0x00415748  9a 99 bb 41

is the memory contents. Read from LSB on the left side (Intel, little-endian machine), this is 0x41bb999a or indeed 1102813594.

Generally, however, the integer and float are stored in the same bytes. Depending on how you access the union, you get the integer or floating point interpretation of those bytes. The size of the memory space, again, depends on the implementation, although it's usually the largest of its constituents aligned to some fixed boundary.

Why is the value such as it is in your (or mine) case? You should read about floating-point number representation for that (look up ieee 754)

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • Hmm, instead of "largest of its constituents" you probably mean the most restrictive. –  Mar 04 '10 at 04:41
  • 4
    @rogue: according to the standard - "The size of a union is sufficient to contain the largest of its members" – Eli Bendersky Mar 04 '10 at 04:42
  • iirc, from k&r, "Although machines vary, for each machine there is a most restrictive type: if the most restrictive type can be stored at a particular address, all other types may be also." -- but I suppose you're right, since the standard is always right, + 1 either way. –  Mar 04 '10 at 05:24
  • 1
    @rogue, you're talking about alignment, so both of you are right. The union should be correctly aligned for all its members, usually defined by the most restrictive, and it should be large enough for the largest of its members. – Secure Mar 04 '10 at 09:11
5

The result is depends on the compiler implementation, But for most x86 compilers, float and int will be the same size. Wikipedia has a pretty good diagram of the layout of a 32 bit float http://en.wikipedia.org/wiki/Single_precision_floating-point_format, that can help to explain 1102813594.

If you print out the int as a hex value, it will be easier to figure out.

printf("%x\n", tst.i);
John Knoeller
  • 33,512
  • 4
  • 61
  • 92
4

With a union, both variables are stored starting at the same memory location. A float is stored in an IEEE format (can't remember the standard number, you can look that up[edit: as pointed out by others, IEEE 754]). But, it will be a two's complement normalized (mantissa is always between 0 and 10, exponent can be anything) floating point number.

you are taking the first 4 bytes of that number (again, you can look up what bits go where in the 16 or 32 bits that a float takes up, can't remember). So it basically means nothing and it isn't useful as an int. That is, unless you know why you would want to do something like that, but usually, a float and int combo isn't very useful.

And, no, I don't think it is implementation defined. I believe that the standard dictates what format a float is in.

Jeff Walker
  • 1,656
  • 1
  • 18
  • 36
  • 3
    C++ standard doesn't mandate IEEE-754 compliant FP representation--but encourages it with the std::numeric_limits::is_iec559 member (equivalent to IEEE-754). Also, denormalized numbers are valid as well. – Drew Hall Mar 04 '10 at 04:53
  • It is probable that you remember better than I do. Thanks. Is this the same for C? – Jeff Walker Mar 04 '10 at 05:02
3

In union, members will be share the same memory. so that we can get the float value as integer value.

Floating number format will be different from integer storage. so that we can understand the difference using the union.

For Ex: If I store the 12 integer value in ( 32 bits ). we can get this 12 value as floating point format.

It will stored as signed(1 bit), exponent(8 bits) and significant precision(23 bits).

sganesh
  • 1,731
  • 1
  • 13
  • 14
1

I wrote a little program that shows what happens when you preserve the bit pattern of a 32-bit float into a 32-bit integer. It gives you the exact same output you are experiencing:

#include <iostream>

int main()
{
    float f = 23.45;
    int x = *reinterpret_cast<int*>(&f);

    std::cout << x; // 1102813594
}
David G
  • 94,763
  • 41
  • 167
  • 253