I have two unions declared
typedef union
{
struct
{
unsigned short n1 : 4;
unsigned int n2 : 4;
} s;
unsigned int val;
} unionA;
typedef union
{
struct
{
unsigned int n1 : 4;
unsigned int n2 : 4;
} s;
unsigned int val;
} unionB;
I assign the same values to val
as
unionA uA;
unionB uB;
uA.val = 0xba;
uB.val = 0xba;
I expected both the first nibble (represented by n1) to be 0xa
and the second nibble (represented by n2) to be 0xb
in both cases. However, it is 0xb
only in unionB
. It is 0xc
in unionA
.
I am running Visual Studio 2019 on Windows 11.
My understanding was the behavior had to be the same regardless of the datatype of the bitfields. What causes this difference?
Unions in C++ are not the same as unions in C. In C++, there is only one member active at any time, and reading from a non active member is undefined behavior. From cppreference:
The union is at least as big as necessary to hold its largest data member, but is usually not larger. The other data members are intended to be allocated in the same bytes as part of that largest member. The details of that allocation are implementation-defined, but all non-static data members will have the same address (since C++14). It is undefined behavior to read from the member of the union that wasn't most recently written.
Since std::variant
(c++17) was introduced, I am not aware of any use of unions in C++. The purpose of a union is to save memory, not to perform type punning.