Вопрос по warning:

Это вариант, так изначально и планировал. Но когда-то в каком-то аддоне, кажется для дигиспарка, сталкивался с проблемой, когда new вызывал ошибку, а вот calloc работал нормально. Соответственно и вопрос - а с calloc можно сделать правильно и без предупреждений? Блин, плаваю я с указателями ))

Это не разговор о программировании.

Стыдно, да. Но проблему имел, решил с помощью calloc и почему-то теперь к new имею предубеждения ))

ты спрашивал как сделать правильно, я написал. А то, што ты new боишься, дак это не сюда, это к врачам.

1 лайк

Ну все, застыдили. Наданапицца (с) ))

1 лайк

Вооот, все предубеждения как рукой снимаеть.

2 лайка

кстате, код можно сократить до

buttons[0] = new shButton(BTN_1_PIN);

в массив попадет либо адрес созданной кнопки, либо nullptr, если new память не выделил. В любом случае, ты же перед обращением к кнопке из массива проверяешь, что там не NULL? Ведь проверяешь же???

Да, сократил

Спойлер
#include <shButton.h>

#define BTN_1_PIN 4
#define BTN_2_PIN 6
#define BTN_3_PIN -1

class ButtonGroup
{
private:
  shButton *buttons[3] = {NULL};

  bool isValid(uint8_t _btn)
  {
    bool result = false;

    if (buttons != NULL && _btn < 3)
    {
      result = buttons[_btn] != NULL;
    }

    return result;
  }

public:
  ButtonGroup() {}

  void init()
  {
#if (BTN_1_PIN >= 0)
      buttons[0] = new shButton{BTN_1_PIN};
#endif

#if (BTN_2_PIN >= 0)
      buttons[1] = new shButton{BTN_2_PIN};
#endif

#if (BTN_3_PIN >= 0)
      buttons[2] = new shButton{BTN_3_PIN};
#endif
  }

  uint8_t getButtonState(uint8_t _btn)
  {
    uint8_t result = BTN_RELEASED;

    if (isValid(_btn))
    {
      result = buttons[_btn]->getButtonState();
    }

    return result;
  }
};

ButtonGroup buts;

void setup()
{
  Serial.begin(9600);
  buts.init();
}

void loop()
{
  switch (buts.getButtonState(0))
  {
  case BTN_DOWN:
    Serial.println("button1 - click");
    break;
  case BTN_DBLCLICK:
    Serial.println("button1 - dblclick");
    break;
  }
  switch (buts.getButtonState(1))
  {
  case BTN_DOWN:
    Serial.println("button2 - click");
    break;
  case BTN_DBLCLICK:
    Serial.println("button3 - dblclick");
    break;
  }
  switch (buts.getButtonState(2))
  {
  case BTN_DOWN:
    Serial.println("button3 - click");
    break;
  case BTN_DBLCLICK:
    Serial.println("button3 - dblclick");
    break;
  }
}

Ну дык

Спойлер
  bool isValid(uint8_t _btn)
  {
    bool result = false;

    if (buttons != NULL && _btn < 3)
    {
      result = buttons[_btn] != NULL;
    }

    return result;
  }
  uint8_t getButtonState(uint8_t _btn)
  {
    uint8_t result = BTN_RELEASED;

    if (isValid(_btn))
    {
      result = buttons[_btn]->getButtonState();
    }

    return result;
  }

Для того ж и замышлялось.

ЗЫ: и вот какая интересность выскочила. Если использую все три кнопки, то скетч занимает

Скетч использует 3520 байт (11%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 290 байт (14%) динамической памяти, оставляя 1758 байт для локальных переменных. Максимум: 2048 байт.

А вот если какую-нибудь кнопку исключаю, т.е. номер пина = -1, то скетч уже занимает

Скетч использует 3552 байт (11%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 290 байт (14%) динамической памяти, оставляя 1758 байт для локальных переменных. Максимум: 2048 байт.

Хотя, казалось бы - объект кнопки физически в памяти не создается ))

Правильнее параметр конструктора передавать в круглых скобках.
И это

не работает так как ты задумал, я проверял, значение из фигурных скобок подставляется только в нулевой элемент массива. В данном случае это неважно, ибо массив твой лежит в секции инициализированных данных и там ноль при рестарте будет автоматом, можно инициализатор совсем не писать. Но вот в случае например int Array[5] = {10}; ты прям сильно удивишься результату.

Ага, зря упростил )))

В первом варианте было же shButton *buttons[3] = {NULL, NULL, NULL};, вот так и оставим, значится ))

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

1 лайк

Я понял. Это меня когда-то сбило с толку что-то вроде этого

И таких пособий в сети овердохрена ))

Ну, нулями он и так заполнится. А не нулями, я проверял - хрен.
Но, у меня С++11, мошт в новых стандартах этого лжывого языка уже всё проправили, я нинаю

у мня счас Ардуины под рукой нету, но ты у себя проверь вот так, и в сетапе массив на печать выведи

Сейчас уезжаю, после обеда проверю ))

IDE 2.3.2 из коробки

int a[10] = { 10 }, b[10] = { 100, 111, 112 };

Вывод:

a: 10; 0; 0; 0; 0; 0; 0; 0; 0; 0; 
b: 100; 111; 112; 0; 0; 0; 0; 0; 0; 0; 
1 лайк

Я ему отдалась при луне,
А он взял мои девичьи груди,
И узлом завязал на спине.
Вот и верь после этого людям.

@Feofan, спасибо. Всё, как я и говорил, нулями оно само инициализируется, а не нулями, только столько, сколько инициализаторов.

1 лайк

Представляю, через какие Альпы! У Вашего shButton имеется конструктор. Какой же леший его вызовет при использовании calloc?

Хммм… как говорят (или не говорят, хрен их знает) наши англоязычные коллеги: “bread save cable”.

Как, впрочем и достоверных видео работы вечных двигателей :slight_smile:

2 лайка

Это была другая библиотека, и там просто создавался массив ))

void init(uint8_t _taskCount)
{
  TASKCOUNT = (_taskCount) ? _taskCount : 1;
  taskList = (shTask *)calloc(TASKCOUNT, sizeof(shTask));
  if (taskList == NULL)
  {
    TASKCOUNT = 0;
  }
}

Изначально использовал new, но когда что-то (уже не помню что) делал на дигиспарке, компилятор начал ругаться на строку с new, а вот calloc переварил без возражений. Понятно, что это проблема аддона, но ковыряться в аддоне желания не было, да и резона тоже ))