0

What I've heard about union is that it will assign the memory space for biggest sized variable within it. Here I'm trying to assign 'same' value in two different ways , but its ending up problematic.

First,

union h {
    int a;
    char b;
};

int main()
{
    union h h1;
    h1.b = 'X';
    printf("%d %c\n",h1.a, h1.b );
    return 0;
}

The output would be a large random number followed by 'X'

-1674402216 X

When I tried assigning h1.a also into a number,

union h {
    int a;
    char b;
};

int main()
{   
    union h h1;
    h1.a = 1;
    h1.b = 'X';
    printf("%d %c\n",h1.a, h1.b );
    return 0;
}

This gives the output

88 X

Can someone help me to figure out what exactly is happening here ?

Thankyou :)

timrau
  • 22,578
  • 4
  • 51
  • 64
Ajmal Moochingal
  • 177
  • 1
  • 10
  • 3
    A `union` can hold the value of **one** of its members, the *active member* (that's the one that was most recently written to). Accessing a member that's not active is *undefined behavior* in general (there are exceptions described in the C standard). As both members share the storage space, what did you expect? –  Oct 05 '17 at 09:42
  • Thanks for your reply. I expected it to get displayed as '88 X' itself. Reason : h1.b is assigned value 'X', and I expected the variable h1.a also would reflect the same change. – Ajmal Moochingal Oct 05 '17 at 09:47

1 Answers1

4

Union members occupy same space in memory. So your union looks something like this:

N-1 ...
    --------
N   ||X||a||
N+1 |   |a||
N+2 |   |a||
N+3 |   |a||
... |      |
    --------
    ...

(Assuming system with 32 bit integer.)

By assiging X you have also modified one byte of your un-initialized a. Your value (-1674402216) can be interpreted as 9C32A658 in base 16. You least significant byte is 58 HEX, which is ASCII code of X adn your other three bytes kept their initial uninitialized value.

In your second case you first initialized int to 1 (which set all but least significant byte to 0), then you have overwritten least significant byte by X have gotten 88 (ASCII code of X) when interpreted as int, and original 'X', when looking at char member.

Not to forget to mention: Layout like this is implementation defined. Standard does say, as mentioned in comments to you question, that you should not actually access member not written last while at the same time, it is a common practice to use them exactly to do this (see this threads: Why do we need C Unions?, What is the strict aliasing rule?).

dbrank0
  • 9,026
  • 2
  • 37
  • 55