tags:

views:

147

answers:

4
union a
{
 int x;
 char a[2];
}

If we assign 512 value to x and try to print a[0] and a[1] then what will be the output please explain how?

+3  A: 

I the depends on the endianess of the platform. On little-endian platforms (Intel) a[0] will have the least significant byte of the integer (4 bytes), so a[0] will hold 0x00 and a[1] 0x02

Fernando Miguélez
@caf: Unlikely. The hex representation of 512 is 0x200. On a little endian platform with a 4 byte integer you'll have 00 02 00 00 in order of ascending address. So a[1] will be 2.
JeremyP
Ahh, of course.
caf
A: 

Unions in C share same memory space, that is, both x and a[2] start at the same memory location. When you assign the value to one of them, the other gets overwritten.

In your case, when you assign 512 to x, you'll write it's bytes to char as well, like Fernando Miguélez just explained...

veljkoz
+5  A: 

According to the standard, the result of writing to one member of a union, then reading from another isn't defined. Just about anything could happen.

Realistically, if you run the code on a little-endian machine, a[0] will probably be 0, and a[1] will probably be 2. On a 16-bit big-endian machine, a[0] would be 2 and a[1] would be 0. On a 32-bit big-endian machine, (the nonexistent, as you've defined things) a[2] would be 2, and a[0], a[1], &a[3] would be 0.

Jerry Coffin
I thought that it was implementation defined, not undefined. I could be wrong. Also, worth noting that this is called "type punning".
detly
Accessing an object through an expression of another type is generally Undefined Behavior. The two main exceptions are (1) layout-compatible structs and (2) access as a `char[]` (which is how `memcpy` can work).
MSalters
I don't think this is correct. [C99](http://goo.gl/A6yq) (with corrigenda) 6.5.2.3 (Structure and union members) says in a footnote, "If the member used to access 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." As @detly says, representations are implementation-defined, so the reinterpretation has to be too.
Matthew Flaschen
@Matthew: I was careful to use "isn't defined" as opposed to "undefined behavior" for this reason. On one hand, the standard says part of it is implementation defined. OTOH, it specifically gives permission for the result to be a trap representation so even just attempting to read the value may cause a trap and your code will cease execution. Under the circumstances, "undefined behavior" vs. "implementation defined" is mostly a distinction without a difference.
Jerry Coffin
@Jerry, you're right that it could cause a trap, and thus is definitely not fully portable. However, I still don't agree that "just about anything could happen." The standard is clear that the it's supposed to attempt reinterpretation, not just shoot nasal demons. The important part of "implementation-defined" is that the implementation has to document its behavior.
Matthew Flaschen
@Matthew: In this case, no, not really. According to §6.2.6.1/5: "If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is producedby a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined. Such a representation is called a trap representation." The documentation requirement only means something if the implementation attempts to meet that requirement -- which few (if any) do.
Jerry Coffin
@Jerry Coffin — if you're interested, the PIC32 C compiler from Microchip does (GCC 3.4 based, so maybe GCC does too?). Appendix A, A.12: **ISO Standard:** "A member of a union object is accessed using a member of a different type (C90 6.3.2.3)." **Implementation:** "The corresponding bytes of the union object are interpreted as an object of the type of the member being accessed without regard for alignment or other possible invalid conditions."
detly
+1  A: 

It depends on the endian-ness of the computer you run it on:

union in effect uses the same memory for your int and your chars, so,

int           512 (ie 0x200)
char[4]       0x00 0x00 0x02 0x00  little endian, so a[0]=0, a[1]=0
char[4]       0x00 0x02 0x00 0x00  big endian   , so a[0]=0, a[1]=2

(actually, I might have little & big endian the wrong way around)

Grim Fandango
Yes, you do....
JeremyP