Часто во встроенном программировании (но не ограничиваясь этим) существует необходимость сериализовать некоторые произвольные struct
, чтобы отправить их по каналу связи или записать в некоторую память.Работа с сериализацией данных без нарушения строгого правила псевдонимов
Пример
Рассмотрим структуру, состоящую из различных типов данных в области N
-aligned памяти:
struct
{
float a;
uint8_t b;
uint32_t c;
} s;
Теперь давайте предположим, что у нас есть функция библиотеки
void write_to_eeprom(uint32_t *data, uint32_t len);
который берет указатель на данные, которые должны быть записаны как uint32_t*
. Теперь мы хотели бы написать s
в eeprom, используя эту функцию. Наивный подход состоял бы в том, чтобы сделать что-то вроде
write_to_eeprom((uint32_t*)&s, sizeof(s)/4);
Но это явное нарушение строгого правила псевдонимов.
Второй пример
struct
{
uint32_t a;
uint8_t b;
uint32_t c;
} s;
В этом случае сглаживание (uint32_t*)&s
не нарушает правила, так как указатель совместим с указателем на первый тип поля, который является законным. Но! Функция библиотеки может быть реализована так, что она выполняет некоторую арифметику указателя для итерации входных данных, тогда как эти арифметические результирующие указатели несовместимы с данными, на которые они указывают (например, data+1
является указателем типа uint32_t*
, но это может указывать на поле uint8_t). Который снова является нарушением правила, как я понимаю.
Возможное решение?
Обертка проблематичная структура в виде объединения с массивами от желаемого типа:
union
{
struct_type s;
uint32_t array[sizeof(struct_type)/4];
} u;
и передать u.array
к библиотечной функции.
Это правильный способ сделать это? Это только правильный способ сделать это? Какие могут быть другие подходы?
Очень простое решение: 'write_to_eeprom (char const * data, size_t len_times_four)'. –
@KerrekSB Как я уже сказал, 'write_to_eeprom' - это библиотечная функция, которая не поддается контролю. И все же, приведение 'float *' в 'char *' является нарушением, не так ли ?. –
@KerrekSB На самом деле нет, это не ... Все может быть сглажено символу 'char *'. –