'struct in union nested - understanding behaviour of type punning
The following code uses a structure inside a union inside a structure inside a union.
#include <cstdio>
union
{
char abcd[4];
struct
{
unsigned ab : 16;
union
{
unsigned xyz : 8;
struct
{
unsigned x : 3;
unsigned y : 5;
};
};
// unsigned x : 3;
// unsigned y : 5;
unsigned d : 8;
};
} SpringOnion;
int main ()
{
SpringOnion.ab = 0xfe57;
SpringOnion.x = 0x5;
SpringOnion.y = 0x1c;
SpringOnion.d = 0xfa;
printf("%x %x %x\n", SpringOnion.x, SpringOnion.y, SpringOnion.xyz);
printf("%x %x %x %x\n", SpringOnion.abcd[0], SpringOnion.abcd[1], SpringOnion.abcd[2], SpringOnion.abcd[3]);
return 0;
}
I compiled using g++ (also checked with gcc) and got the following output on running:
5 1c e5
57 fffffffe 0 0
Is that the expected output?
On defining the union in the following manner:
union
{
char abcd[4];
struct
{
unsigned ab : 16;
union
{
unsigned xyz;
struct
{
unsigned x : 3;
unsigned y : 5;
};
}c : 8;
unsigned d : 8;
};
} SpringOnion;
I get the compilation error:
error: bit-field ‘c’ with non-integral type ‘<unnamed union>::<unnamed struct>::<unnamed union>’
which, on checking up, gives answers which seem to me to be not perfectly relatable.
The answer by Jonathan Leffler https://stackoverflow.com/a/18730706/7920584 points out by saying:
Structures, unions: but then you aren't dealing with simple fields.
But then what kind of field should I be using? Is there something else that can meet my expectations?
Expectation:- I expect the output to be:
5 1c e5
57 fffffffe ffffffe5 fffffffa
Which is similar to what I get upon removing the nested union and using the x :3;
and y :5;
directly in the main struct.
May I know why I am expecting wrong?
Solution 1:[1]
printf("%x %x %x\n", SpringOnion.x, SpringOnion.y, SpringOnion.xyz); ^^^ printf("%x %x %x %x\n", SpringOnion.abcd[0], SpringOnion.abcd[1], SpringOnion.abcd[2], SpringOnion.abcd[3]); ^^^^ ^^^^ ^^^^ ^^^^
Here, you read from an inactive member of a union. You aren't allowed to do that in C++. The behaviour of the program is undefined.
Is that the expected output?
There is no portable expectation for the output. Even if we were to assume that there is a reasonable behaviour defined by the language implementation for reading an inactive union member, there's still no precise definition for allocation of bitfields in the language. That is implementation defined in most regards (in practice, it's determined by the ABI, which varies across different systems).
Furthermore, you have anonymous structs in your union. Anonymous structs are not allowed in C++. The program is ill-formed.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |