Массив переменной длины
- Войдите на сайт для отправки комментариев
Ср, 25/02/2015 - 23:07
Есть некоторый прототип составного устройства... количество подключенных "частей" можно программно определить в setup(). Хочется написать универсальную прошивку для устройства.
"Частей" может быть от 1 до 128 (просто для определенности)
Нужно сделать структуру, в которой будут храниться состояния "частей" (для упрощения посчитаем, что нужно просто сделать массив однотипных значений).
Можно, конечно, сделать сразу массив максимальной длины и пользовать только "значимые" элементы, но, имхо, это расточительство с точки зрения использования скромных ресурсов МК (особенно в случае, если для хранения будут использоваться структуры данных и если "частей" мало (1-2)).
Как быть?
Если не требуется постоянно удалять/создавать элементы, а только один раз создал, потом использовать, то можно реализовать простой неупорядоченный односвязный список и добавлять элементы по необходимости. В этом случае динамическое выделение памяти не так деструктивно для программы. Реализация списка - простенький класс (или даже просто структура) со структурой данных, которую нужно хранить, плюс ссылка на следующий элемент. Либо использовать STL, но тут я не подскажу, сколько оно памяти жрет, не исследовал, думаю будет хуже (с точки зрения жрать память и динамически перераспределять, что не очень хорошо).
Минус списка в том, что если нужен доступ к элементам по индексу - только перебором (есть и другие способы, но это опять же память и динамика - не очень выгодно). А если всегда перебирать все элементы, то пофиг.
Думаю легко найдете в гугле реализацию таких великов :) Я раньше пользовался таким, поскольку был старый компилятор, а теперь STL наше всё. На большом компе, конечно.
Вот, например, тут: http://victor192007.narod.ru/files/cpp_d1.html
Элементы нужно создать сразу после того, как стало понятно, сколько же "частей" подключено (после этого структура данных уже не меняется).
"Велики" - крутые... лихо закручено. Надо подумать (и проверить, насколько это вообще реализуемо на ардуино)...
Ну и получение значения n-ого элемента - будет не самой быстрой операцией (особенно, если n - "далеко" от начала).
Если элементы нужно создать всего один раз, когда известно их количество, то списки ф топку. В этом случае всё тупее и быстрее, а именно (накидал навскидку, не компилировал):
Из минусов, можно легко и просто перескочить за пределы массива (т.е. взять структуру с индексом большим чем array_cnt), например:
В данном варианте все структуры расположены в памяти плоско, т.е. сначала идет одна структура, следом за ней вторая и т.п.
Это один из вариантов и оптимален он только для случая, когда создавать элементы массива нужно всего один раз, когда уже точно известно их количество. Варианты могут быть и другие.
Еще раз:
gp_array - указатель на массив структур. Т.е. gp_array[0] - это структура, а не указатель на структуру. &(gp_array[3]) - это указатель на 4 структуру в массиве (индексы с нуля).
Примеры:
gp_array[0].val1
&(gp_array[4])->val1
Можно использовать указатель на структуру, например, так:
Полный листинг из Visual Studio:
Результат работы программы:
Можно, конечно, сделать сразу массив максимальной длины и пользовать только "значимые" элементы, но, имхо, это расточительство с точки зрения использования скромных ресурсов МК (особенно в случае, если для хранения будут использоваться структуры данных и если "частей" мало (1-2)).
И тем не мение, именно так верней. Используя динамическое распределение памяти (malloc в setup) задействовать остальную будет проблематично. Т.к. при разработке программы прийдется все время помнить, что возможен и плохой вариант - все 128 частей присутствуют и оставлять память на этот случай свободной. Как вариант - урезание части функционала, т.е. при 1-2 частях работает все что можна а при 128 - только минимум, для которого хватает памяти. При этом повышается требование к качеству кода, надо нормально работать в обоих случаях. ИМХО - забудте о этом.
В процессе разработки легко выделить максимум данных и проверить наличие свободной памяти, так что провода и кнопки в руки и пробовать, хотя и посчитать несложно
А толку с этого? Если сказано максимум 128 частей, то вариант, что на них не хватает памяти никого не устроит. Потом прийдется иметь резерв свободной памяти на все 128, пусть даже распределите в malloc тока на два, а оставшиеся 126 будут просто не использоватся или использоватся для доп. функционала как я писал. А если доп. функционала не предвидится (что в общем типично), то почему бы не распределить всю память на 128 частей и забыть о проблеме? Такая специфика динамического распределения в МК в отличии от ПК, в котором смысл экономить память есть, т.к. её подберет другое приложение, кеш и т.д. А в МК подобрать "экономию" некому.
Вцелом логично. Однако задача сформулирована поверхностно, потому можно только философствовать.
Простой пример, для вывода отладочных сообщений может не хватить памяти, если выделить сразу все 128 блоков.
Спасибо, обсуждение привело к переосмыслению задачи и "выделению памяти" в голове, что существенно изменило подход к написанию кода на МК :)
Отлично! :)
Обычно решение задачи зависит от условий.
Но динамика тоже иногда нужна. Был проект, где хорошо было выделить максимальный буфер.
Удачи