Bhanu Teja
Bhanu Teja

Reputation: 1

Strange output when using union type members

My code:

#include<stdio.h>

union U{
    int x;
    char y;
};

int main()
{
    union U u1;
    u1.x = 258;
    u1.y = '0';
    printf("%d%d",u1.x,u1.y);
    return 0;
}

Strangely, the output is 30448.

Can someone please explain how this happens?

Upvotes: 0

Views: 221

Answers (2)

anastaciu
anastaciu

Reputation: 23802

You maybe missunderstanding the purpose of a union. It is meant to store only one variable at a time, but this variable can have multiple types. The last variable stored will overwrite the previous.

In your case u1.y (which is '0', it's relevant to remind that the 1 byte ASCII decimal representation for '0' is 48), is the last value stored, this corresponds to last 2 digits of your output as you print '0' by its ASCII decimal representation.

As for the first part of the output, note that you overwrite the int variable 258, which is presumably 4 bytes (but for the sake of explanation I will assume it's 2 bytes) with the 1 byte wide char variable 48.

The binary value for 258 (assuming 2 bytes wide int) is:

|0|0|0|0|0|0|0|1|0|0|0|0|0|0|1|0|

|   2nd byte    |   1st byte    |              

The binary value for 48 (1 byte wide char variable) is:

| | | | | | | | |0|0|1|1|0|0|0|0|

                |   1st byte    | 

When you overwrite the two byte union variable with a one byte variable only the 8 least significant bits(least significant byte) will be overwritten, so you'll end up with:

|0|0|0|0|0|0|0|1|x|x|x|x|x|x|x|x|
| | | | | | | | |0|0|1|1|0|0|0|0|

|0|0|0|0|0|0|0|1|0|0|1|1|0|0|0|0|

And this is the binary representation of 304.

So yor code first prints the 2 bytes wide (for the sake of the examle) int 304 and next the 1 byte wide int 48 (the ASCII int representation of '0'), hence the output 30448.

Note that this behavior is not undefined.

ISO/IEC 9899:2017 N2176

§ 6.5.2.3

97) If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called “type punning”). This might be a trap representation.

§ 6.2.6.2

6 - When a value is stored in an object of structure or union type, including in a member object, the bytes of the object representation that correspond to any padding bytes take unspecified values.51) The value of a structure or union object is never a trap representation, even though the value of a member of the structure or union object may be a trap representation.

7 - When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values.

For confirmation you can use:

printf("%p %p\n", (void*)&u1.x, (void*)&u1.y);

This will print the memory address of both u1.x and u1.y and you will not be shocked to find that they are the same.

Upvotes: 3

pmg
pmg

Reputation: 108938

You cannot read a member of a union other than the one last written into

#include<stdio.h>
union U{
int x;
char y;
};

int main()
{
    union U u1;
    u1.x = 258; // write into member x: OK
    u1.y = '0'; // write into member y: OK
    printf("%d%d",u1.x,u1.y); // read both member x and y: WRONG
                              // can only read member y
    return 0;
}

Upvotes: -1

Related Questions