Let's say I have data, such as below:
union
{
struct
{
char flags : 4;
uint16_t : 12;
}
char data[2];
}
I understand how to make this code run regardless of byte endianness on a platform. I am asking to be sure that my understanding of how it would be stored on the different endians is correct.
As I understand it: If I were to store a uint16 in the 12 bit uint, both endians would drop the 4 highest bits. Big-endian would store the remaining 4 high bits in the same byte as the flags, and the rest in a separate byte. Little-endian would store the 4 lowest bits in the same byte as the flags, and the rest in a separate byte.
Is this right?
It depends on the compiler and the target platform's ABI. See, e.g. the rules for GCC bit-fields: The order of allocation of bit-fields within a unit is Determined by ABI. Also each field is supposed to be declared int
or unsigned int
, not uint16_t
.
If you want to control the data format, you can use shifting and masking to assemble the data into a uint16_t
. If your aim is to write the data out in a well-defined format, you can write the uint16_t
bytes in the required endianness or just assemble the data into 2 bytes and write them in the required order.
Unless you find language spec docs that promise what you want, or your compiler docs make clear promises and you're using the same compiler for big and little endian CPUs, don't rely on C/C++ compilers to all do something like this the same way.