Использование std::list в программировании Arduino
При попытке компиляции
#include <list>
std::list<byte> l = { 7, 5, 16, 8 };
в Arduino IDE (с ATtinyCore для ATtiny4313) я получаю следующее сообщение:
ошибка: список: нет такого файла или каталога
#include <список>
Как использовать стандартный C++ std::list
с Arduino/ATtiny?
@Basj, 👍4
2 ответа
Лучший ответ:
Я поддерживаю предложение Мишеля Кейзерса использовать простой массив, особенно учитывая крошечный объем ОЗУ в вашем MCU (всего 256 байт).
Относительно удаления элементов из списка и с учетом того, что ваш список будет максимум 16 байт, вам не нужно придумывать: просто вернитесь назад элементы, которые прошли мимо того, который вы удалили. Это не займет много времени.
Вот упрощенная реализация списка, который может содержать не более 16 байт и поддерживает удаление:
class List {
public:
byte length;
byte data[16];
void append(byte item) {
if (length < 16) data[length++] = item;
}
void remove(byte index) {
if (index >= length) return;
memmove(&data[index], &data[index+1], length - index - 1);
length--;
}
};
Обратите внимание, что для этого требуется всего 17 байт ОЗУ (максимум 16 элементов плюс счет длины). Нет vtable, так как у него нет виртуальных методов. Ты Если хотите, можете сделать его более привлекательным, сделайте этот шаблон параметризованным тип данных и максимальная длина, добавьте средства доступа и т. д., но если вы просто пишут простой скетч (в отличие от общей цели библиотеку), я бы рекомендовал сделать ее как можно более простой.
Пример использования на основе вашего псевдокода:
List l { .length = 3, .data = { 12, 82, 29 } };
l.remove(1);
Это действительно приведет к списку [12, 29].
Я не думаю, что эта библиотека поддерживается attiny (и вообще Arduino).
Однако помимо этого не рекомендуется его использовать, поскольку неизвестно, сколько памяти и флэш-накладных расходов он потребляет.
Особенно проблема с памятью по двум причинам:
- Внутренне вы не знаете точных структур данных, используемых для списка. Наиболее эффективно он будет использовать только 4 байта (4 раза по 1 байту для массива), однако, поскольку это класс под капотом, добавляется виртуальная таблица, и кто знает, какая еще память (максимальная емкость, текущая емкость список и т. д.).
- Также при добавлении/удалении элемента из списка либо копируется весь список, либо используются какие-то трюки с указателями. В первом случае вы получаете пробелы в памяти, во втором случае возможно (и используется дополнительная память для указателей).
Мой совет — использовать только простой массив и определить максимум массива во время компиляции (если это возможно). Не такой гибкий, но надежный, требует меньше памяти и более надежен с устройством с низким объемом SRAM, таким как Attiny (и Arduino в целом).
Удаление элементов
На основе вашего первого комментария:
Удаление элементов действительно является проблемой, однако обратите внимание, что если вы используете стандартную библиотеку, она может скопировать весь массив (исключая) новый элемент, поэтому временно у вас будет двойной массив И пробел в памяти.
Есть несколько способов реализовать это самостоятельно:
- Если вы хотите только удалить элементы (и никогда не добавлять), добавьте новый массив с логическими значениями, которые обозначают, какие из них присутствуют, а какие удалены (например, delete[4] = 1 означает, что элемент 4 удален. Это стоит всего 1 бит на элемент.
- Используйте два массива с элементами и каждый раз копируйте их туда и обратно. На самом деле это не приведет к разрыву памяти, но вам понадобится хранилище, необходимое для двух массивов. И сохраните переменную, которая из двух массивов является «текущей».
Спасибо за ваш ответ. Я был бы рад использовать простой массив (в любом случае мне нужен список максимум 16 байт). Единственное, что я не могу легко сделать с простым массивом, это это (псевдокод): L = [12, 82, 29] => L.remove(index=1) => L = [12, 29], т.е. удалить элементы в середине или в начале. Любая идея, как сделать это легко, не изобретая велосипед?, @Basj
Я обновил свой ответ (работает только для удаления элементов, добавление элементов может быть более сложным)., @Michel Keijzers
- Какие есть другие IDE для Arduino?
- Как устранить сообщение об ошибке "assignment of function 'void digitalWrite (uint8_t, uint_8)"?
- Оптимизация кода для ATtiny10
- Управление конфигурациями через EEPROM путем записи в шестнадцатеричный файл
- Управление сервоприводом с помощью ATtiny13A
- Альтернативная IDE для компиляции и запуска кода arduino?
- Как уменьшить использование глобальных переменных? Attiny85
- C++ против языка Arduino?
Очень полезно, большое спасибо! Оба ответа теперь очень хороши, я не знаю, какой выбрать!, @Basj
PS: что это за синтаксис:
List l { .length = 3 ... };
Это ярлык для чего-то еще, чтобы создать экземпляр класса?, @Basj@Basj: это [совокупная инициализация](https://en.cppreference.com/w/cpp/language/aggregate_initialization): просто заполнение полей данных, [как в обычном C](https://en.cppreference. com/w/c/language/struct_initialization). Удобно, когда вам лень писать правильный конструктор. ;-), @Edgar Bonet
Спасибо @ЭдгарБонет. Вы видите умный/легкий способ найти индекс данного элемента? Пример: L = [12, 82, 29, 128].
L.indexof(29)
вернет2
. Это последнее, что мне нужно в этих списках :), @Basj@Basj: я не вижу умного пути. Но список настолько мал, что можно использовать грубую силу: просто перебирайте список, пока не найдете нужный элемент., @Edgar Bonet
Я сделал это, работает!, @Basj