Копирование структуры в байтовый массив
У меня есть 1-байтовая прагма упакованная структура в C, которую я хочу скопировать в байтовый массив для целей сериализации, чтобы отправить через последовательный порт.
#pragma pack(push, 1)
typedef struct {
uint8_t ck_a;
uint8_t ck_b;
} UBXChecksum_t ;
#pragma pack(pop)
Каков наилучший способ сериализации в байтовый массив, я должен просто использовать memcpy()
?
void writeStructToArray(const void* inStruct,
const uint16_t inLenStruct,
uint8_t* const outArray)
{
memcpy(outArray, inStruct, inLenStruct);
}
или лучше использовать побайтовое копирование, делая указатель типов?
void writeStructToArray(const void* inStruct,
const uint16_t inLenStruct,
uint8_t* const outArray)
{
for(uint16_t i = 0; i < inLenStruct; i++)
{
outArray[i] = ((uint8_t*)inStruct)[i];
}
}
2 ответа
Как прокомментировал Камил Цук, ваши два предложения почти одинаковы с некоторой возможной разницей в скорости.
Другой вариант - использовать объединение:
typedef struct {
uint8_t ck_a;
uint8_t ck_b;
} UBXChecksum_t ;
union convert {
UBXChecksum_t checksum;
char buffer[sizeof UBXChecksum_t];
};
UBXChecksum_t checksum;
union convert converter;
converter.checksum = checksum;
passArrayToSomeFunction(converter.buffer, sizeof(converter.buffer));
Вам не нужно копировать данные, чтобы преобразовать их в массив. Вы можете передать указатель на структуру (если необходимо, char*
или же void*
) и размер структуры функции, которая отправляет данные в последовательный порт. Пример:
typedef struct {
uint8_t ck_a;
uint8_t ck_b;
} UBXChecksum_t ;
int sendData(void *buf, size_t size);
UBXChecksum_t checksum;
/* ... */
int rc = sendData(&checksum, sizeof(checksum));
Все эти варианты отправляют внутреннее представление структуры в виде двоичных данных. Обычно "сериализация" понимается как способ преобразования данных в независимый от платформы формат.
Отправка двоичных структур данных работает, если принимающая система того же типа и использует тот же компилятор. Могут возникнуть проблемы, когда принимающая система использует другой порядок байтов или разные размеры типов данных.
В вашем случае у вас есть структура двух uint8_t
значения, поэтому размер является фиксированным, и порядок следования байтов не является проблемой.
Можно отправлять двоичные данные, если для структуры требуется соответствие заданному протоколу двоичных данных, и вы готовы обработать порядок байтов, если это необходимо.
memcpy() не учитывает отсутствие доступа к системе. таким образом, если Sender имеет порядковый номер с прямым порядком байтов, а получатель имеет младший порядковый номер, тогда в получателе будет конфликт для значения структурной переменной
Со вторым методом вы знаете, как подготовлен поток байтов в отправителе, поэтому на принимающей стороне он также может получать соответственно, чтобы убедиться в правильном значении структурной переменной.
Если порядковый номер систем одинаков, а порядковый номер не имеет значения, тогда и метод будет служить цели, и memcpy() будет быстрее сравниваться с назначением значения байта в цикле.