Reputation: 2567
#include <stdio.h>
int main()
{
union Data
{
char str[20];
int i;
float f;
}data;
data.i=20;
data.f=220.5;
printf("%d\n",(data.i));
return 0;
}
The output is:1130135552. I used gcc complier on Ubuntu 16.04 LTS.
Can someone explain the output?
The members data.i
and data.f
occupy same memory location, so output should be 220. But why output is 1130135552?
Upvotes: 3
Views: 763
Reputation: 3666
As you are already aware that union
shares memory location between the members inside. In case of union
compiler allocated the memory equal to the max size of the member and use the same memory for all the members.
Hence when you execute data.f=220.5;
, shared memory location between i
and f
holding data.i=20;
got overwritten to a new value (220.5) with binary representation as follows :
Now again, when this value is read as a signed integer int
it will be interpreted without conversion as 1130135552
in decimal representation. Hence you are getting 1130135552
.
Further if you want to use all members of union, then struct is the answer.
struct Data
{
char str[20];
int i;
float f;
} data;
data.i=20;
data.f=220.5;
printf("%d\n",data.i);
For more information on union
and struct
Please refer the following from Difference between Structure and Union:
Upvotes: 6
Reputation: 4288
data.i
and data.f
share the same memory, but the interpretation of a value is different in integer and float.
With a float converter you get following values:
220.5 in float means:
sign: 1
exponent: 134
mantissa: 1.72265625 encoded as :6062080
binary representation:0 10000110 10111001000000000000000 (sign, exponent, mant.)
hex representation: 0x435c8000
dezimal representation:1130135552 (the value you get!!)
Upvotes: 1
Reputation: 567
As explicited by phoxis, the standard declares that the value is unspecified.
However, pragmatically, this is a good example of binary interpretation.
I assume the width for an int
and float
on your platform is 32 bits, and a floating-point value follows the IEEE 754 representation.
What happens here:
data.f=220.5;
This statement writes the floating-point value as binary 0100 0011 0101 1100 1000 0000 0000 0000
in the memory location of data
, overwriting any previous value.
The next time the value is accessed is when read as an integer: data.i
member access in your printf
call. The value read, in binary, is still 0100 0011 0101 1100 1000 0000 0000 0000
, and as a signed integer, this is interpreted without conversion as 1130135552
.
If you want the value to be converted, you have to read the value as a floating-point (using data.f
) and convert it to an integer value with a cast:
printf("%d\n",(int)(data.f));
Upvotes: 2
Reputation: 234715
If I may, let's restrict this answer to the case where sizeof(float)
is the same as sizeof(int)
, that float
is a single precision IEEE754 type, and int
is a 2's complement type. If you don't understand what I'm saying here, ignore this paragraph for now: it's here in an attempt to make this answer watertight; a bit like the legalese in a financial contract.
A float
is a remarkable type capable of representing numbers in a large range with a remarkable amount of precision. The format it uses internally to achieve this is a a complex one. If you want to know more, see https://en.wikipedia.org/wiki/IEEE_754.
When you write data.f = 220.5;
, you are setting the first sizeof(float)
bytes in your union
to have the memory associated with the constant 220.5f
.
But an int
uses an entirely different format. When you output the int
member of the union, you recover the int
with value 1130135552
. This is related to the 220.5f
in that both have exactly the same pattern of bits.
The char str[20];
in your union
is a red herring.
Upvotes: 2
Reputation: 61910
According to C11 Section 6.5.2.3 Footnote 95
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.
The specific output depends on the layout of the members in memory and the type. Therefore, when you store data.f
and then access data.i
, the bit patterns in the memory of data.f
is reinterpreted as an integer.
Note the following:
int a = 1;
float b = 1;
These two although may seem to have a similar layout on memory, but they are stored differently. In the case of integer, it will be generally stored in a two's complement format (although it can be other formats as well), and a floating point will be generally stored using the IEEE754 format (although it can be different). Therefore, trying to interpret a number stored using IEEE754 as integer will get you something totally different.
Also, not that, according to C11 Section 6.2.6.1 Paragraph 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.
Therefore, if you assign to a member of an object of a union, then the values in the bytes of other location which is not used by the member which you assigned will have unspecified values.
Upvotes: 6