Это вариант, так изначально и планировал. Но когда-то в каком-то аддоне, кажется для дигиспарка, сталкивался с проблемой, когда new
вызывал ошибку, а вот calloc
работал нормально. Соответственно и вопрос - а с calloc
можно сделать правильно и без предупреждений? Блин, плаваю я с указателями ))
Это не разговор о программировании.
Стыдно, да. Но проблему имел, решил с помощью calloc
и почему-то теперь к new
имею предубеждения ))
ты спрашивал как сделать правильно, я написал. А то, што ты new боишься, дак это не сюда, это к врачам.
Ну все, застыдили. Наданапицца (с) ))
Вооот, все предубеждения как рукой снимаеть.
кстате, код можно сократить до
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};
, вот так и оставим, значится ))
я ж говорю, инициализатор в данном случае можно вапще не писать, нулями он сам инициализируется при старте. Вот если бы тебе надо было инициализировать ненулевым значением, то хрен, оно бы попало только в нулевой элемент массива, а не во все.
Я понял. Это меня когда-то сбило с толку что-то вроде этого
И таких пособий в сети овердохрена ))
Ну, нулями он и так заполнится. А не нулями, я проверял - хрен.
Но, у меня С++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;
Я ему отдалась при луне,
А он взял мои девичьи груди,
И узлом завязал на спине.
Вот и верь после этого людям.
@Feofan, спасибо. Всё, как я и говорил, нулями оно само инициализируется, а не нулями, только столько, сколько инициализаторов.
Представляю, через какие Альпы! У Вашего shButton
имеется конструктор. Какой же леший его вызовет при использовании calloc
?
Хммм… как говорят (или не говорят, хрен их знает) наши англоязычные коллеги: “bread save cable”.
Как, впрочем и достоверных видео работы вечных двигателей
Это была другая библиотека, и там просто создавался массив ))
void init(uint8_t _taskCount)
{
TASKCOUNT = (_taskCount) ? _taskCount : 1;
taskList = (shTask *)calloc(TASKCOUNT, sizeof(shTask));
if (taskList == NULL)
{
TASKCOUNT = 0;
}
}
Изначально использовал new
, но когда что-то (уже не помню что) делал на дигиспарке, компилятор начал ругаться на строку с new
, а вот calloc
переварил без возражений. Понятно, что это проблема аддона, но ковыряться в аддоне желания не было, да и резона тоже ))