0

When I initialize an integer first to that of a float in a union, then why does the value of the integer get changed? I have even tried interchanging by initializing float first to that of the integer but even then I get the value of the float to be zero.

Here's my code

#include <stdio.h>
#include <stdlib.h>
union t{
    int x;
    float y;
} u;
int main()
{
    u.x = 2;
    printf("original value of integer: %d\n", u.x);
    printf("original address of integer: %p\n", u.x);
    u.y = 8.23;
    printf("value of float: %f\n", u.y);
    printf("address of float: %p\n", u.y);
    printf("after value of integer: %d\n", u.x);
    printf("after address value of integer: %p", u.x);
    return 0;
 }

this is the image of the result of the above code

Please can you explain this behavior?

the busybee
  • 10,755
  • 3
  • 13
  • 30
  • 7
    `%p", u.x` is not an address, it's printing value (and it is _undefined behavior_). `why does the value of the integer gets changed?` Do you understand what an union is? – KamilCuk Jul 02 '20 at 16:43
  • There is no initialization in the code shown; there are only assignments. – Jonathan Leffler Jul 02 '20 at 16:51
  • 1
    Don't post images of plain text. Include the text in your question. Format it as code — use triple-backquote followed by `none` to specify that the output should not be formatted for any particular language (and mark the end with another triple backquote line). – Jonathan Leffler Jul 02 '20 at 16:53
  • You can't just change a format specifier from `%d` to `%p` and expect it to magically take the address of the argument. You need to do it explicitly, e.g. `&u.x`. And strictly speaking, you should cast it to `void *`, e.g. `(void *)&u.x`. Then you can use `%p`. – Tom Karzes Jul 02 '20 at 17:07
  • thank you, @TomKarzes now I understood how the address should be printed. But can u pls explain why the value is getting changed? – Rohit_Sharma Jul 03 '20 at 08:44
  • @KamilCuk I didn't understand that's why I approached this forum – Rohit_Sharma Jul 03 '20 at 08:46
  • Sure. This forum is rather programming enthusiast that already know programming to ask about specific programming problems. It's not a good place to learn. I suggest you rather approach a [good C book](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list). – KamilCuk Jul 03 '20 at 08:49
  • hey thanks, @KamilCuk for suggesting me this – Rohit_Sharma Jul 03 '20 at 09:49
  • @Rohit_Sharma `u.x` and `u.y` overlap in memory (that's what a `union` does). So assigning to either one of them invalidates the value of the other. If that's ok, then a `union` makes sense since it takes less memory than a `struct`. If it doesn't, then you need to use a `struct`. – Tom Karzes Jul 03 '20 at 12:01

1 Answers1

0

The printf format specifier has to match the type of argument passed. %p expects a void * argument, passing u.x that has the type of int to it is undefined behavior (also see this question), and results on your implementation and architecture in printing the number in hex representation using upper case characters (as this is what usually %p uses). Ie. 0x4103AE14 = 1090760212.

To print the address of a variable use address of operator and because the result of &u.x type is int* explicitly cast it to void* to match %p requirement:

printf("address of float: %p\n", (void*)&u.y);
printf("The address of u.x is: %p\n", (void*)&u.x);

Which will result in printing the same address.

why does the value of the integer get changed?

Because they share the memory.

Please can you explain this behavior?

Most probably your compiler uses IEEE 745 to represent floating point numbers. The number 8.23 is most probably represented as a single precision floating point number 8.229999542236328125 that is encoded as 0x4103AE14 (compare ex. with this site or this site).

Because the floating point variable and integer variable share the memory in an union (and stars are in proper positions - on your platform sizeof(int) == sizeof(float)) the same bit representation of the float value is interpreted as an int. So when you access the u.x variable of that union, the bit representation of a float number encoded as 0x4103AE14 is interpreted as an int, which results in the number, well, 0x4103AE14 (because endianess of float and int is same) which is equal to 1090760212 in dec.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111