Размер структуры tm (datetime) отличается в ESP32 от linux64x

esp32 time sd

Я записываю двоичные данные на свою SD-карту. Я регистрирую объект datetime типа "tm", размер которого в ESP32 составляет 36 байт. Когда я создаю дату-время типа " tm " в Linux, оно составляет 56 байт.

ESP32 запись tm на SD: [дата и время tm = 36 байт]

time_t t = std::time(nullptr);
tm datetime = *std::localtime(&t);
uint16_t t = file.write((const uint8_t *)&datetime, sizeof(datetime)); // ==36 байт.

ПК [tm datetime = 56 байт] (скомпилирован с использованием g++ в linux 64)

tm datetime;
std::ifstream fileStream(filename, std::ios::binary);
fileStream.read((char *)&datetime, sizeof(datetime));

tm определяется во времени.h:

struct tm
{
  int   tm_sec;
  int   tm_min;
  int   tm_hour;
  int   tm_mday;
  int   tm_mon;
  int   tm_year;
  int   tm_wday;
  int   tm_yday;
  int   tm_isdst;
#ifdef __TM_GMTOFF
  long  __TM_GMTOFF;
#endif
#ifdef __TM_ZONE
  const char *__TM_ZONE;
#endif
};

В моей структуре tm нет "tm_gmtoff" или "tm_zone", даже если бы она была, она не добавит до 56 байт.

Как мой tm может быть 56 байт на компьютере? Если у кого-то есть лучший способ регистрации объекта datetime без этой проблемы, дайте мне знать.

, 👍0

Обсуждение

`размер(int) " на arduino (AVR) равен 2, на большинстве других платформ-4., @PMF

Зачем входить в двоичный файл? Войдите в виде текста в формате " дата +"%FT%T%:z". Если вам действительно нужен двоичный файл, запишите "time_t", а не "strcut tm"., @Edgar Bonet

@PMF Я использую ESP32, не уточнил, моя ошибка!, @washichi

@EdgarBonet вводит текст слишком медленно, я регистрируюсь на частоте 100 Гц, используя sd.h lib. почему ведение журнала time_t лучше в двоичном формате?, @washichi

Тогда пишите не всю структуру целиком, а по элементам, создавая свою собственную структуру данных., @Michel Keijzers

Компоновка strcut tm зависит от реализации. Напротив, "time_t" обычно представляет собой простое целое число с очень небольшими вариациями в разных реализациях: 32 или 64 бита и, возможно, другая эпоха (которая фиксируется простым добавлением константы)., @Edgar Bonet

Кроме того, у вас есть проблемы с выравниванием и размерами доступа к данным. Записи в структуре будут выровнены по адресам, которые будут определяться тем, к чему может получить доступ базовая архитектура (если она может читать/записывать только целые слова, каждый байт будет выровнен по границе слов, расширяющей вашу структуру). Вы никогда не должны использовать структуры системного уровня при хранении или передаче данных (если только они не предназначены специально для этого). Вместо этого определите свои собственные и "упакуйте" их, чтобы устранить любые проблемы с выравниванием и заполнением., @Majenko


1 ответ


Лучший ответ:

2

Вы не можете доверять структурам системного уровня для хранения или передачи данных между различными системами. Основными причинами являются:

  1. Различные размеры типов данных (16 / 32 / 64 битовые вставки, float против binary и т. Д.)
  2. Различия в выравнивании элементов структуры из-за оптимизации и ограничений базовой архитектуры

Если вы не работаете с системной структурой, специально разработанной для межсистемного взаимодействия, вы должны определить свою собственную и уделить особое внимание компоновке.

  1. Всегда используйте явно определенные типы переменных (например, uint8_t, int32_t и т. Д.), Чтобы гарантировать, что оба конца всегда согласуют размеры хранилища данных
  2. Всегда "упаковывайте" свою структуру (__атрибут__((упаковано)), чтобы свернуть любые специально выровненные переменные в пространство, необходимое для хранения этих переменных

Пункт 2 требует особого внимания, если вы делаете гораздо больше, чем заполнение структуры и ее сохранение / передача. Рекомендуется никогда не делать больше, чем создавать экземпляр структуры, заполнять его, сохранять, а затем выбрасывать. Если вы начнете выполнять расширенные операции с указателями на структуру, вы рискуете повредить код упаковки в случае изменения выравнивания. Кроме того, доступ к упакованным структурам часто немного медленнее из-за более сложного кода, обычно необходимого для чтения / записи отдельных полей в них (особенно если в базовой архитектуре отсутствуют операции с байтами).

,

Спасибо! несколько человек прокомментировали решения, но вы объяснили причину. Также спасибо за ваше [blogpost](https://hackingmajenkoblog.wordpress.com/2016/03/25/fast-efficient-data-storage-on-an-arduino), очень полезно!, @washichi