Reputation: 172
Let's consider a union of integers of different sizes. Is it guaranteed that if a number fits the range of each of the integer types, it can be written to and read out from any of the union data members correctly?
E.g. this code
union U {
int32_t i;
int16_t s;
} u;
u.s = 1000;
std::cout<<u.i<<std::endl;
I verified that it prints correctly "1000" on one computer. Is it guaranteed to work the same on any other system? I guess on any system the endianness would be the same for any integer type, so it's rather a question whether the union is guaranteed to use the less significant bytes of the larger integer for the smaller one?
I know this has no chance to work for negative numbers, so let's consider non-negative numbers only.
Upvotes: 0
Views: 687
Reputation: 41962
No, that only works in little endian. In big endian the bytes are stored from the most significant position down. 0xdeadbeef
will be stored in memory as ef be ad de
in little endian and de ad be ef
big endian in memory so reading 2 bytes from the start address will result in 0xbeef and 0xdead in those machines respectively
However you're getting undefined behavior, because you're writing the smaller 2-byte field first then read the larger one. That means the high 2 bytes of int32_t
will contain garbage. That's disregarding the fact that using union
in C++ is already UB. You can only do that in C
If you write the larger field first the read the smaller one then it works even for signed types:
u.i = -1000;
std::cout << u.s << '\n';
This will print out as expected on a little endian machine
Upvotes: 2
Reputation: 348
The union will always be only as big as necessary to hold its largest data member.
The other data members are allocated in the same bytes as the largest member.
The details of how the 'other members' are allocated is implementation defined. By this definition, the answer is no it's not guaranteed. See: https://en.cppreference.com/w/cpp/language/union "Explanation"
Since C++14, all non-static data members of the union will have the same address; but that doesn't say anything about endianness or implementation support.
Upvotes: 1