switch и структурированный массив - ошибка expression must have a constant value -- attempt to access run-time storage
- Войдите на сайт для отправки комментариев
Вс, 17/02/2019 - 16:19
Добрый день! Прошу помочь знатоков С++ и Arduino. Записываю массив данных в структурированный массив. После чего мне необходимо обработать данные оператором switch. Фрагмент кода:
#include <Arduino.h>
const uint8_t cntPins = 8;
struct listData_t
{
const uint8_t pinNumsber;
const uint8_t pinID;
};
const listData_t pins[cntPins] =
{
{32, 2}, {34, 3}, {36, 4}, {38, 14}, {40, 15}, {42, 11}, {44, 13}, {46, 5}
};
void setup()
{
Serial.begin(115200);
Serial.println(F("Start..."));
for (uint8_t i=0; i<cntPins; i++)
{
Serial.print(pins[i].pinNumsber);
Serial.print(F("\t"));
Serial.println(pins[i].pinID);
}
}
void loop()
{
delay(1500);
for (uint8_t i=0; i<cntPins; i++)
{
switch (pins[i].pinID)
{
case pins[0].pinID:
Serial.print(F("pinNumber > "));
Serial.println(pins[i].pinNumsber);
break;
}
}
}
При компиляции возвращаются 2 ошибки:
expression must have a constant value -- attempt to access run-time storage
the value of 'pins' is not usable in a constant expression.
Если в case поставить const uint8_t N, то копилируется без ошибок и код работает. Кто может подсказать в какую сторону "копать"?
А вот чем Вам двумерный массив не нравится? Или там более глобальные замыслы?
Попробуйте в 3 строке проименить #define cntPins 8
здесь
casepins[0].pinID:должна быть целая константаНапримерcase 10: ....
case 'a': ...
и т.д.
здесь
casepins[0].pinID:должна быть целая константаНапримерcase 10: ....
case 'a': ...
и т.д.
Я это понимаю, вопрос, есть вариант подставить в case целую константу, получив ее из массива?
Получается, мне нужно или дублировать константу, которую подставлять в case, или уходить на одномерные массивы, что очень не удобно и не желательно, или сначала, перед switch "выдергивать" данные из массива в локальные переменные, которые подставлять в case, что тоже, как-то кривовато... Может есть, какой-то вариант, я не профессионал в данном вопросе, поэтому и прошу подсказку в какую сторону копать...
А вот чем Вам двумерный массив не нравится? Или там более глобальные замыслы?
Попробуйте в 3 строке проименить #define cntPins 8
количество записей в массиве - не проблема, проблема в целочисленной константе, которую "кушает" case...
Да, задумка более глобальная, нежели во фрагменте кода...
Я это понимаю, вопрос, есть вариант подставить в case целую константу, получив ее из массива?
Константа в case должна быть доступна на момент компиляции. Т.е. напрямую или через подстановку. Но никак не по вычисляемому на этапе исполнения индексу массива. Select-case в объектном коде выглядит набором джампов (считай goto), поэтому адреса "приземлений" должны быть вычислены при компиляции.
Получается, мне нужно или дублировать константу, которую подставлять в case, или уходить на одномерные массивы, что очень не удобно и не желательно, или сначала, перед switch "выдергивать" данные из массива в локальные переменные, которые подставлять в case, что тоже, как-то кривовато... Может есть, какой-то вариант, я не профессионал в данном вопросе, поэтому и прошу подсказку в какую сторону копать...
Чтобы понять куда копать - надо узнать для чего копать. Если бы граф Монте-Кристо копал без понимания направления, то скелет его нашли бы в каземате.
Ну не обязательно же через switch - case делать. Можно ведь и через if - else if конструкцию.
Ну не обязательно же через switch - case делать. Можно ведь и через if - else if конструкцию.
Громостко и неудобно получается, если if и else if использовать...
Чтобы понять куда копать - надо узнать для чего копать. Если бы граф Монте-Кристо копал без понимания направления, то скелет его нашли бы в каземате.
Получается выход один, вычислить все переменные, хранящиеся в многомерных массивах до их использования в операторе switch и case... Другого выходе нет?!
Для чего копать:
1. Хранить данные в многомерном структурированном массиве
2. Использовать switch и case используя данные их многомерных структурированных массивов
2. Использовать switch и case используя данные их многомерных структурированных массивов
Использовать для... <тут пример использования>
Громостко и неудобно получается, если if и else if использовать...
Что же там громоЗДкого! Даже компактнее получится. А если нужны условные break-и, то их можно ретурном заментить, если оформить в функции.
Использовать для... <тут пример использования>
Как пример использования:
struct listBTN_t { const uint8_t idBTN; const char nameBTN[5]; const char textBTN[5]; }; const listBTN_t buttons[3] = { {0, "bt10", "t10"}, {1, "bt11", "t11"}, {2, "bt12", "t12"} }; switch (RXdata) { case buttons[0].idBTN: // некоторая последовательность функций break; case buttons[1].idBTN: // некоторая последовательность функций break; case buttons[2].idBTN: // некоторая последовательность функций break; }при этом RXdata это данные полученные по UART или RS-485
На поверхности лежит поиск в цикле соответствия RXData и idBTN. Switch нацеливается на переменную, в которую помещается найденный индекс элемента массива, который соответствует условию. Все индексы определены на этапе компиляции и проблемы не возникнет. Можно через define дать им осмысленные имена.
На поверхности лежит поиск в цикле соответствия RXData и idBTN. Switch нацеливается на переменную, в которую помещается найденный индекс элемента массива, который соответствует условию. Все индексы определены на этапе компиляции и проблемы не возникнет. Можно через define дать им осмысленные имена.
Да, всё верно, полученные внешние данные я сравниваю с id кнопки, чтобы выполнить то или иное действие по нажатию локальной кнопки. Если явно задать имена, тогда при создании многомерного массива, писать в него не физические значения id, а имена, тем самым запишеться значение присвоеное через #define.
#define idName1 = 0 #define idName2 = 1 #define idName3 = 2 struct listBTN_t { const uint8_t idBTN; const char nameBTN[5]; const char textBTN[5]; }; const listBTN_t buttons[3] = { {idName1, "bt10", "t10"}, {idName2, "bt11", "t11"}, {idName3, "bt12", "t12"} }; switch (RXdata) { case idName1: // некоторая последовательность функций break; case idName2: // некоторая последовательность функций break; case idName3: // некоторая последовательность функций break; }как-то так, или всё же есть более правильный способ, через #define?
Я имел в виду более сложный вариант, но, если idNameX никогда не будет несовместимого с case типа, то можно и на этом остановиться.
Я имел в виду более сложный вариант, но, если idNameX никогда не будет несовместимого с case типа, то можно и на этом остановиться.
idNameX - всегда число (uint8_t или const uint8_t), как id компонента.
А какой более сложный вариант, если не сложно, пример дайте пожалуйста
Я его описал выше - поиск в цикле. Искомая строка сравнивается, например, с buttons[i].nameBTN, совпало - из цикла выскакиваем, найденный индекс (i) суём в switch.
Я его описал выше - поиск в цикле. Искомая строка сравнивается, например, с buttons[i].nameBTN, совпало - из цикла выскакиваем, найденный индекс (i) суём в switch.
Спасибо! Невнимательно прочел тот пост.