Обеспечение того, чтобы сохраненные данные записывались таким образом, чтобы их можно было прочитать на нужных платформах, на мой взгляд, не квалифицируется как «взлом». Однако слепое сохранение (возможно, упакованной) структуры в двоичном формате и ожидание простого и удобного чтения ее обратно.
Вам необходимо обрабатывать каждое поле отдельно, так как компилятор может добавить заполнение между полями, которое появится в «двоичном дампе» struct
, но это полностью зависит от компилятора и, следовательно, очень плохо для взаимодействия между платформами. .
Я бы, вероятно, выбрал разумную точность для собственных int
полей структуры, скажем, 32 бита, и написал бы что-то вроде этого:
void tm_serialize(FILE *out, const struct tm *tm)
{
int32_serialize(out, tm->tm_sec);
int32_serialize(out, tm->tm_min);
/* and so on */
}
struct tm tm_deserialize(FILE *in)
{
struct tm tm;
tm.tm_sec = int32_deserialize(in);
tm.tm_min = int32_deserialize(in);
/* and so on */
return tm;
}
Где, конечно, int32_serialize()
и int32_deserialize()
просто пишут (и читают) двоичное представление 32-разрядного целого числа в известном (например, с прямым порядком байтов) формате, которое хорошо определено и легко читается назад на любую платформу.
ОБНОВЛЕНИЕ: Сериализация строк, конечно, может быть выполнена точно таким же образом, один популярный формат такой же, как макет C в памяти, т. Е. Массив char
с нулевым символом в конце. Тогда у вас будет просто:
void string_serialize(FILE *out, const char* string);
int string_deserialize(FILE *in, char *string, size_t max);
Здесь функция string_deserialize()
должна иметь ограничение размера буфера, чтобы она ничего не переполняла, читая слишком много. Я представлял возвращаемое значение, чтобы указать успех / неудачу, поэтому вызывающий код может принять любые меры, которые он хочет.
В приведенном выше примере я не стремился к минимизации пространства, сводимой к минимуму, поскольку комментатор указал, что многие из полей, которые int
во время выполнения, на самом деле не нуждаются в такой точности, поэтому они могут быть сериализовано во что-то меньшее. Если вы хотите сделать это, конечно, было бы тривиально изобрести соответствующие функции, такие как int8_serialize()
и т. Д., И использовать правильную для каждого поля.