У меня есть некоторый существующий код C ++, который отправляет получает массив по сети uint32_t
. Из-за изменения в моем протоколе я хочу заменить каждую запись в этом массиве на пару из двух uint16_t
с, и, если возможно, я бы хотел сделать это без изменения количества битов, которые я посылаю по сети. Очевидный способ объединить два значения uint16_t
в одно значение шириной 32 бита - выполнить низкоуровневую упаковку битов в uint32_t
и оставить определение массива без изменений. Таким образом, код отправителя будет выглядеть так:
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));
}
И код получателя будет выглядеть так:
//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
}
Однако, это уродливо, небезопасно и зависит от жестко закодированных магических чисел. Интересно, возможно ли сделать то же самое, определив двухэлементную структуру, которая «должна» быть точно такого же размера, как uint32_t
:
struct data_item_t {
uint16_t field1;
uint16_t field2;
};
Тогда код отправителя будет выглядеть так:
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};
}
И код получателя будет выглядеть так:
//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
}
Будет ли это работать эквивалентно битовой упаковке uint32_t
с? Другими словами, будет ли массив элементов содержать те же биты, когда я использую struct data_item_t
, как когда я использую uint32_t
и упаковку битов? Основываясь на правилах заполнения структуры , я думаю, что структура, содержащая два uint16_t
s, никогда не будет нуждаться в каком-либо внутреннем заполнении для правильного выравнивания. Или это на самом деле мой компилятор, и мне нужно что-то вроде __attribute__((__packed__))
, чтобы гарантировать это?