Об инициализации структур

Во-во! Главная мысль там, что ажно

Это вообще не самые хилые дела :slight_smile:

Вот здесь говорят о высших материях, а я, похоже, столкнулся с банальными граблями.

Есть такая структура, поля которой инициализируются в void setup():

struct
{
  byte a;
  byte b;
  float c;
  float d;
  float e;
  byte f;
  int g;
  bool h
} k1;

Я её пишу в EEPROM и читаю оттуда же. Указываю адрес структуры, адрес в EEPROM и sizeof(k1)
Столкнулся вот с чем. При чтении поля выводятся в монитор порта с каким-то сдвигом! Танцевал я с этой проблемой до тех пор, пока не заменил типы byte и bool на int. Проблема, как бы, решилась.
Подскажите, пожалуйста, проблема все-таки решилась или “как бы”?

про выравнивание слышал чонить?

читай про #pragma pack(push, 1)

3 лайка

Не должно быть таких структур.
Если что, это и есть ответ на твой вопрос.

2 лайка

Про выравнивание слышал. Боюсь я его, но попробую. А чем не выравнивание, если типы содедржат чётное число байт?

Переделал структуру так:

struct
{
  int a;
  int b;
  float c;
  float d;
  float e;
  int  f;
  int g;
  int  h;
} k1;

Похоже, что стало работать нормально. Но проблема сдвига вернулась.

Обратился к совету @DetSimen : прочитал про
#pragma pack(push, 1)
Решил попробовать у себя. И тут выяснилось вот что. Скетч я заливаю через программатор USBasp из HEX - файла. Перед заливкой скетча EEPROM заполнена этой структурой. Но при чтении из EEPROM получается такой сдвиг, что во всех полях nan. А при очередных циклах записи - чтения всё работает нормально. Работаю с нулевым адресом EEPROM. Похоже, что структура меняет свой адрес после прошивки, а затем её адрес восстанавливается.

Нет, больше похоже, что руки и ноги у тебя растут из одного и того же места. Но так как информации недостаточно, гадать не буду.

Ну и что??? Попробовал #pragma pack(push, 1).
После прошивки через USBasp (через шнур не заливал) эта хрень осталась.

Сам ты, @DetSimen три дня не умывался. Здесь кроме @ЕвгенийП мало кто объяснит - в чем причина проблемы.

вот была тема,
может поможет

3 лайка

Сэр в курсе, что выравнивание может быть на границу одного, двух, четырех, восьми или шестнадцати байтов?
Я бы начал с того, что переупорядочил поля в структуре так, чтобы они в упакованном виде были выровнены на естественную границу. Ну не должно четырехбайтовое число начинаться по смещению 2!

И еще: если предполагается использование структуры для хранения либо передачи информации, в ней не должно быть полей типа int.

А как тогда в составе структуры передать, например, число ‘-3160’ ?

signed short не предлагать?

Чем он лучше int16_t ?

Ничем, это одно и тоже, только для int16_t нужно дополнительно подключатт <stint.h>

Это которые типы? byte? или bool?

Нет. Которые в #41.

Я цитировал ваше сообщение 40. Вы там писали про структуру, которую определили только в #41? Сильно

Если вернуться к сути - мало конкретики. Начните с того, что укажите, о каком контроллере речь? И далее покажите код, как вы сохраняете структуру и как читаете обратно. А то может дело не в выравнивании, а в банальной программной ошибке

1 лайк

Arduino - UNO. Код сейчас покажу, но перед этим напомню, что это получается после прошивки через USBasp. Затем при записи-чтении работает корректно.

Вызовы:
to_eeprom(&k1, 0, sizeof(k1)); // запись
from_eeprom(&k1, 0, sizeof(k1)); // чтение

Процедуры:

void to_eeprom(void *x, int adress, int razmer)
{
  byte* ptr = (byte*) x;
  int adr = adress;
  for (int i = 0; i < razmer; i++)
  {
    EEPROM.update(adr, *(ptr + i));
    adr++;
  }
}
void from_eeprom(void *x, int adress, int razmer)
{
  byte* ptr = (byte*) x;
  int adr = adress;
  for (int i = 0; i < razmer; i++)
  {
    *(ptr + i) = EEPROM.read(adr);
    adr++;
  }
}

чему равен?

Все логично же, уж сколько раз тут к этому подводят. Программа пишет и читает одинаково размещенную структуру. А предварительно сформированный дамп залитый через программатор сформирован с иными правилами упаковки. Или меняйте упаковку в программе, или меняйте формат предварительно подготовленного дампа.

Прошивать тоже надо уметь. Показывайте, как Вы это делаете и как готовите дамп для прошивки.