I have some existing C++ code that sends an receives an array of uint32_t
over the network. Due to a change in my protocol, I want to replace each entry in this array with a pair of two uint16_t
s, and if possible I would like to do this without changing the number of bits I send over the network. An obvious way to combine two uint16_t
values into a single 32-bit-wide value is to do low-level bit-packing into a uint32_t
, and leave the array definition unchanged. So the sender's code would look like this:
uint32_t items[ARR_SIZE];
for(std::size_t i = 0; i < ARR_SIZE; ++i) {
//get uint16_t field1 and field2 somehow
items[i] = static_cast<uint32_t>(static_cast<uint32_t>(field2) << 16)
| static_cast<uint32_t>(field1));
}
And the receiver's code would look like this:
//receive items
for(std::size_t i = 0; i < ARR_SIZE; ++i) {
uint16_t field1 = static_cast<uint16_t>(items[i] & 0xffff);
uint16_t field2 = static_cast<uint16_t>(items[i] >> 16);
//do something with field1 and field2
}
However, this is ugly, type-unsafe, and relies on hard-coded magic numbers. I wonder if it is possible to accomplish the same thing by defining a 2-member struct that "should" be exactly the same size as a uint32_t
:
struct data_item_t {
uint16_t field1;
uint16_t field2;
};
Then, the sender's code would look like this:
data_item_t items[ARR_SIZE];
for(std::size_t i = 0; i < SIZE; ++i) {
//get uint16_t field1 and field2 somehow
items[i] = {field1, field2};
}
And the receiver's code would look like this:
//receive items
for(std::size_t i = 0; i < ARR_SIZE; ++i) {
uint16_t curr_field1 = items[i].field1;
uint16_t curr_field2 = items[i].field2;
//do something with field1 and field2
}
Will this work equivalently to the bit-packed uint32_t
s? In other words, will the items array contain the same bits when I use struct data_item_t
as when I use uint32_t
and bit-packing? Based on the rules of structure padding, I think a struct containing two uint16_t
s will never need any internal padding to be properly aligned. Or is that actually up to my compiler, and I need something like __attribute__((__packed__))
to guarantee it?