Структура с указателем внутри

Тема в разделе "Микроконтроллеры AVR", создана пользователем parovoZZ, 22 янв 2019.

  1. parovoZZ

    parovoZZ Гуру

    Указатель на структуру разобрали. Теперь задачка посложнее =)
    Код (C++):
    struct Payload_t                    // Структура с данными
    {
        uint8_t    *Data;                // Указатель на данные
        uint8_t    Length;               // Размер данных в байтах
        uint8_t   Channel;                // Данные с этого канала
    };
    Я хочу по указателю в поле Data записать Length данных.
    Пишем:
    Код (C++):
        struct Payload_t Payload;
        Payload.Length = SEND_LEN;
        Payload.Data = malloc(sizeof(Payload.Length));
    Записываю данные с помощью функции:
    Код (C++):
    void SPI_ReadArray(uint8_t num, uint8_t *data)
    вот так:
    Код (C++):
    SPI_ReadArray(Payload.Length, Payload.Data);
    а читаю так
    Код (C++):
    uint8_t Data3       = *(Payload.Data);
    Я же всё правильно сделал?
     
    Tomasina нравится это.
  2. DetSimen

    DetSimen Guest

    Делай лучше так

    Указатель на структуру разобрали. Теперь задачка посложнее =)

    Код (C++):
    struct Payload_t                    // Структура с данными
    {
       uint8_t   *Data;               // Указатель на данные
       uint8_t   Length;             // Размер данных в байтах
       uint8_t  Channel;               // Данные с этого канала

      Payload_t(){memset(this,0,sizeof(Payload_t));};
      ~Payload_t(){ delete [] Data;};
    };
    Я хочу по указателю в поле Data записать Length данных.
    Пишем:

    Код (C++):
       struct Payload_t Payload;
        Payload.Length = SEND_LEN;
        Payload.Data =  new uint8_t[SEND_LEN];

       //  ошибка, у тебя здесь выделится 1 байт ->    malloc(sizeof(Payload.Length));
      //   а не SEND_LEN, убери sizeof из скобок
     
    Записываю данные с помощью функции:

    Код (C++):
    void SPI_ReadArray(uint8_t num, uint8_t *data)
    вот так:

    Код (C++):
    SPI_ReadArray(Payload.Length, Payload.Data);
    а читай так

    Код (C++):
    uint8_t Data3      = Payload.Data[N];
     
    Последнее редактирование модератором: 22 янв 2019
    Tomasina нравится это.
  3. Asper Daffy

    Asper Daffy Иксперд

    Дед, тогда ещё конструктор нужен, который туда NULL загонит. А то если структура не статическая, то NULL туда никто за нас не засунет. А если там точно NULL, то if в деструкторе не нужен. delete на NULL вполне адекватно работает.
     
    parovoZZ, Алексей.А и DetSimen нравится это.
  4. DetSimen

    DetSimen Guest

    Не буду спорить с Вами, в таких тонкостях не разбираюсь, век живи, век учись. :)
    Я думал, конструктор по умолчанию обнулит все поля свои сам, но, видимо, я ошибаюсь с классом хранения этого типа.
    Поправил.
     
    Последнее редактирование модератором: 22 янв 2019
  5. Тогда уж и конструктор копий и оператор присваивания непременно :)
    Код (C++):
    struct ByteArray_t {
        ByteArray_t() {
            this->size = 0;
            this->data = 0;
        }
        ByteArray_t(const ByteArray_t& org) {
            this->size = 0;
            this->data = 0;
            operator = (org);
        }
        ByteArray_t& operator = (const ByteArray_t &rhs) {
            if (this != &rhs) {
                clear();
                this->size = rhs.size;
                if (rhs.size) {
                    this->data = new uint8_t[rhs.size];
                    memcpy(this->data, rhs.data, rhs.size);
                }
            }
            return *this;
        }
        ~ByteArray_t() {
            clear();
        }
        void clear() {
            delete[] this->data;
            this->data = 0;
            this->size = 0;
        }
        size_t size;
        uint8_t* data;
    };
     
     
  6. DetSimen

    DetSimen Guest

    Это ты щас типа блеснул?
     
  7. parovoZZ

    parovoZZ Гуру

    Это же си плас плас?
    Да, точняк. Надо прекращать кодить в 2 часа ночи) А больше некогда(
    Я там умолчал - в конкретно данном случае мне нужен всего один (он же первый) байт. А компилятор не скажет
    я же массив явно не объявлял?
     
  8. Если будет вызван оператор присваивания, а вы его не перегрузили, то сработает простое копирование класса и в деструкторе первого экземпляра будет освобождено то что выделялось, а в деструкторе второго получите небо в алмазах.
     
    DetSimen нравится это.
  9. DetSimen

    DetSimen Guest

    к указателю в С всегда можно обратиться индексатором, за исключением указателя на void. И смещение он вычислит правильно.
     
    parovoZZ нравится это.
  10. DetSimen

    DetSimen Guest

    Ну да. Но так как здесь памяти мало от слова совсем, на безопасности кода всячески ыканомют. Не думаю, что он эти структуры друг другу присваивать будет. Но ты прав, безусловно, это я по скудоумию своему не подумал.
     
  11. Я указал на потенциально опасный код, конечно же лучше потрольть, даже веселее становится.
     
  12. DetSimen

    DetSimen Guest

    я прошу прощения.
     
  13. DetSimen

    DetSimen Guest

    Оправданием мне может служить только то, что я не то что вапще не программист, но еще и спахмелью. Пардоньте-с. :(
     
  14. Если хотите защититься от вызова оператора присваивания и конструктора копий, используйте не структуру а класс и сделайте их приватными, пусть даже пустыми.
     
  15. Asper Daffy

    Asper Daffy Иксперд

    Кто или что мешает сделать это в структуре?
     
    DetSimen нравится это.
  16. Согласен, меня с толку сбило что C++ обрабатывает обратную совместимость с программами на C, и там всё было паблик.
     
  17. parovoZZ

    parovoZZ Гуру

    А через указатель нельзя?
    А чем работа через имя структуры сакрально отличается от работы через структурную переменную? Я в первом случае не смогу вот так инициализировать:
    Код (C++):

    typedef struct Payload_t {...};

    .......
    struct Payload_t Payload = (Payload_t)
    {
        .*Data = malloc ()...,            
        .Length = ...,            
        .Channel = ...,            
    };
     
    ?
     
    Последнее редактирование: 22 янв 2019
  18. DetSimen

    DetSimen Guest

    Шта?
     
  19. Объявляю приватным и где то в коде вызываю оператор присваивания
    Код (C++):
    struct ByteArray_t {
      ByteArray_t() {
        this->size = 0;
        this->data = 0;
      }
      ~ByteArray_t() {
        if (this->data) {
          delete[] this->data;
        }
        this->data = 0;
        this->size = 0;
      }
      size_t size;
      uint8_t* data;
    private:
      ByteArray_t(const ByteArray_t& org) {
      }
      ByteArray_t& operator = (const ByteArray_t &rhs) {
        return *this;
      }
    };
    void setup() {
      struct ByteArray_t a, b;
      a = b;
    }
    void loop() {
    }
    компилятор это не пропустит
    Код (C++):
    /tmp/arduino_modified_sketch_193172/sketch_jan22a.ino: In function 'void setup()':
    sketch_jan22a:18:16: error: 'ByteArray_t& ByteArray_t::operator=(const ByteArray_t&)' is private
       ByteArray_t& operator = (const ByteArray_t &rhs) {
                    ^
    sketch_jan22a:24:5: error: within this context
       a = b;
         ^
    exit status 1
    'ByteArray_t& ByteArray_t::operator=(const ByteArray_t&)' is private
     
     
    DetSimen нравится это.
  20. DetSimen

    DetSimen Guest

    достаточно, памойму, сделать их protected.
     
    Asper Daffy нравится это.