Копирование структуры в байтовый массив

У меня есть 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() будет быстрее сравниваться с назначением значения байта в цикле.

Другие вопросы по тегам