дублировать структуру typedef через указатель

#c #pointers #types

#c #указатели #типы

Вопрос:

У меня есть следующий определенный typedef и *ButtonSettingPtr в качестве указателя:

  typedef struct
    {
      void     *next;
      char**   buttonsetting;
      char*    currentsetting;
      uint16_t presetid;
      uint16_t currentcounter;
      uint16_t maxsize;
      uint16_t buttonid;
    } ButtonSetting;

typedef ButtonSetting *ButtonSettingPtr;


class Options {
 private:
  ButtonSettingPtr settings;
  ButtonSettingPtr preset1;
public:
Options();
void newSetting(char** _setting, uint16_t _maxsize, uint16_t _buttonid);
// some other stuff defined here
}
  

С помощью функции newSetting() я добавляю несколько новых записей в свой
экземпляр typedef! Теперь я хотел бы сохранить все эти настройки
(this-> настройки) в другой указатель (this-> preset1) через memcpy, чтобы
позже вызвать их снова с помощью другой функции, поскольку я использую
this-> настройки в нескольких других функциях (getCurrentSetting), которые
работают довольно хорошо и т. Д.

 char *Options::getCurrentSetting(uint16_t _buttonid) {
  ButtonSettingPtr setting = (ButtonSettingPtr)this->settings;
  while (setting != NULL)
  {
    if (setting->buttonid == _buttonid) {
      char * tmpsetting = 
        setting->buttonsetting[setting->currentcounter];
      return tmpsetting;

    }
    setting = (ButtonSettingPtr)setting->next;
  }
  return NULL;
}
  

Вот в чем проблема:

 void Options::savePreset() {
  memcpy(amp;this->preset1,amp;this->settings,sizeof(amp;this->settings));
}
void Options::loadPreset() {
  memcpy(amp;this->settings,amp;this->preset1,sizeof(amp;this->preset1));
}
  

Кажется, что мой указатель preset1 всегда точно такой же, как
this-> настройки, даже если я меняю настройки между ними. Я
понимаю, что с помощью знака amp;amp он буквально копирует адрес
этого указателя, поэтому неудивительно, что они оба всегда будут точно такими
же. Но то, что я хотел бы скопировать, — это скорее все байты и указать их
на preset1, чтобы позже я мог снова вспомнить все настройки.

Итак, без знака amp;amp мой код просто зависает:

 void Options::savePreset() {
  memcpy(this->preset1,this->settings,sizeof(this->settings));
}
void Options::loadPreset() {
  memcpy(this->settings,this->preset1,sizeof(this->preset1));
}
  

Должен ли я указывать указатель this-> preset1, прежде чем я все
к нему добавлю? Весь код скомпилирован с использованием avr-libc для чипа atmega.

Заранее спасибо за любой полезный совет!

ps: Мое понимание C , безусловно, было лучше, когда я был моложе!

Комментарии:

1. Простите, что я говорю, но этот код выглядит ужасно. Что натолкнуло вас на идею использовать указатели? Или typedef ваших классов? Вы уверены, что не помните язык, который отличался от того, на котором вы были моложе?

2. Единственный C , который я вижу в этом коде, — это class ключевое слово…

3. Нам не дано Options конструктору знать, как они были инициализированы. Я бы рекомендовал попытаться уменьшить проблему, это слишком много информации. На первый взгляд, sizeof(this->settings) это подозрительно. Рассмотрите возможность пересмотра этого, чтобы использовать конструктор копирования вместо memcpy.

Ответ №1:

Похоже, вы создаете самодельный односвязный список. Если вы замените это на std::vector , вы обнаружите, что копировать одно в другое так же просто, как preset1 = settings; (вам не нужно ставить this-> перед всем, если вы просто не предпочитаете этот стиль).

Возможно, вы также захотите заменить char** внутри класса на std::vector<string> , тогда будут скопированы фактические строки.

Комментарии:

1. Это встроенная система. Я использую компилятор avr-gcc, поэтому я не могу использовать удобные функции C (std::vector)

2. @FrescoGamba, компилятор, который не реализует vector , не заслуживает того, чтобы называться C . Извините, что потратил ваше время.

3. Итак, кажется, что он копирует только первую запись связанного списка, если я сделаю это: memcpy(preset1, settings, sizeof(ButtonSetting)); и для загрузки пресета memcpy(settings, preset1, sizeof(ButtonSetting));

4. следовательно, я хотел бы скопировать каждый элемент моего связанного списка? опять я борюсь с синтаксисом!

Ответ №2:

Да, вам нужно предварительно установить malloc1 (нет необходимости разыменовывать его с помощью this-> внутри функции-члена. Если вы хотите дать понять, что это элемент данных класса, назовите его m_preset1 или mPreset1, как вам нравится).

Итак, в вашем конструкторе установите preset1 равным NULL. Затем в вашей функции-члене вы можете:

 void Options::savePreset() {
    if (preset1 == NULL) {
        preset1 = (ButtonSettingPtr)malloc(sizeof (ButtonSetting));
    }
    memcpy(preset1, settings, sizeof(ButtonSetting));
}
  

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

 class Options {
private:
    ButtonSetting settings;
    ButtonSetting preset1;
public:
    Options();
    void newSetting(char** _setting, uint16_t _maxsize, uint16_t _buttonid);
    // some other stuff defined here
}

void Options::savePreset() {
    memcpy(amp;preset1, amp;settings, sizeof(ButtonSetting));
}
  

Обратите внимание, что sizeof(this-> настройки) всегда будет 4 или 8 (в зависимости от 32 или 64-разрядного процессора), потому что вы запрашиваете размер указателя, а не размер структуры.

Комментарии:

1. Кроме того, я знаю, что malloc() не является C ; Я просто использовал соглашение в вопросе OP.

Ответ №3:

 sizeof(amp;this->settings)
  

вернет размер указателя, потому что он фактически является указателем.

 sizeof(this->settings)
  

вернет размер указателя, потому что это указатель.

 sizeof(*this->settings)
  

вернет размер анонимной структуры, на которую также указывают настройки.

А что касается вопроса о необходимости malloc пространства для

  this->preset1
  

зависит от вашего кода. Но это наверняка должно указывать на действительную память!