Arduino.ru
Проблема с обнулением массива
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Подскжите где косяк .
вот этот кусок кода «вешает» программу .
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Если delay(100); выполнить 1440 раз то так и будет)))
А еще у вас Serial лопнет от потока данных
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
1440 * 100 = 144000 мили секунд = 144 секунды =
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Дело в том, что delay и Serial я сделал просто в этом примере в самом скетче такого нет, но всеравно виснит контроллер хоть так, хоть иначе.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
а памяти у вас хватает на него?? у вас там не 4 гига ведь, а int сколько байт занимает в памяти? умножить на 1440 и добавить все остальное. Вобщем не знаете матчасть потому и не работает .
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Я бы, на Вашем месте, выводил на печать отладочную тинформацию. Например, значение счетчика цикла.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
1. сколько оперативной памяти у вашего контроллера?
3. проще и быстрее обнулить массив можно приблизительно так: memset(&tstArr[0], 0, sizeof(tstArr));
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
1. сколько оперативной памяти у вашего контроллера?
3. проще и быстрее обнулить массив можно приблизительно так: memset(&tstArr[0], 0, sizeof(tstArr));
2 — по ссылкам не особо понял как решить проблемму. поменял где можно int на byte но ничего не изменилось
3 — в таком виде компилятор ругается. пробывал обнулить так memset(tstArr, ‘\0’, 1441); компилятор пропустил но проблемма не решилась.
Arduino.ru
подскажите как можно обнулить переменную
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
его надо обнулять при каждом проходе цикла
но сейчас он 8 элементов, а есть будет 80..800 то смотрится это страшновать
ВОПРПОС: можно ли (С и ардуина могут ли?) обявить и обнулить массив такой записью?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
memset ( celoe , 0 ,8);
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
если масив объявлен как
то да. изменили на
уже не прокатит.
прокатит в обоих вар-ах.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
да, memset(celoe,0,8); работает
при этом памяти жрет ровно столько, сколько и byte celoe[8]=<0,0,0,0,0,0,0,0>;
главное не ошибиться и не задавать его больше, чем размер переменной.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
если масив объявлен как
то да. изменили на
уже не прокатит.
прокатит в обоих вар-ах.
В обоих вариантах прокатит будет memset(celoe,0,sizeof(celoe));
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
а разве memset -у надо не число байт заменяемых указывать?
тогда для int будет *2 размер, а long *4.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
а разве memset -у надо не число байт заменяемых указывать?
sizeof() дает размер в байтах, а не число элементов
Забавно, что ТС не приходит в голову набрать в гугле memset и sizeof
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
если масив объявлен как
то да. изменили на
уже не прокатит.
прокатит в обоих вар-ах.
В обоих вариантах прокатит будет memset(celoe,0,sizeof(celoe));
не хотел давать гранату.
далее последовало бы (при отличном от byte)
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
не хотел давать гранату.
далее последовало бы (при отличном от byte)
Почему не работает-то? — работает
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
не хотел давать гранату.
далее последовало бы (при отличном от byte)
Почему не работает-то? — работает
ну то есть оно работает, но как !
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
вопрос был весьма конкретный. и не стоял о иных возможностях
мне достаточно было ответа «да» или «нет»
но спасибо Logik за memset — о нем не знал.
цикл — это старый и самый «школьный» метод. так тчо его даже не рассматривал (если есть иные механизмы)
ну и спасибо b707 за уточнение по sizeof — я думал он дает размер в виде числа элементов, а не в байтах. а щас почитал, оказывается именно для МАССИВОВ он возращает размер в байтах. а для остально (строки например) — просто числом её длинну
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
ну то есть оно работает, но как !
Ну вы других-то совсем за идиотов не держите :) Я ж сразу написал. что sizeof дает длину структуры в байтах, а не число элетнтов. Вот, так. к примеру, работает:
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
цикл — это старый и самый «школьный» метод. так тчо его даже не рассматривал (если есть иные механизмы)
Вы будете удивлены, заглянув внутрь типичному memset’у: https://searchcode.com/codesearch/view/19105601/
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
это я чтото не понял. но похоже sizeof дает размер в байтах самой переменной, вместо её размера в символах.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
ну и спасибо b707 за уточнение по sizeof — я думал он дает размер в виде числа элементов, а не в байтах. а щас почитал, оказывается именно для МАССИВОВ он возращает размер в байтах. а для остально (строки например) — просто числом её длинну
sizeof для любых структур возвращает размер занимаемой памяти в байтах. В том числе для массивов, структур, классов.
И для строк тоже — в байтах. Просто для строки, если это классичемкий ASCII — размер в байтах и в символах совпадает. А вот если строка UTF — то уже нет.
Си-строки (массивы символов)
Си-строки
В прошлом уроке мы разобрали динамические String-строки в реализации Arduino, а сейчас настало время стандартных статических строк языка C/C++. Такая строка представляет собой массив символов типа char (char array) и для неё работает такой же синтаксис, как и для остальных массивов (урок про массивы). Конец строки определяется нулевым символом \0 (или целым число 0 ), за это такой тип строк называют null-terminated string: ноль на конце позволяет программе определять конец строки и её длину. Также это стандартные строки языка Си и поэтому называются cstring.
Текст в кавычках
Любой написанный в двойных кавычках текст «some text» :
- Является строковой константой – string constant
- Имеет тип данных const char* – то есть указывает на свой первый символ в памяти
- Хранится и в программной, и в оперативной памяти микроконтроллера
- Компилятор автоматически добавляет нулевой символ в конец строки ‘\0’ – то есть реальный размер строки всегда на 1 символ больше
- Оптимизируется компилятором – об этом ниже
Объявление как массив
Основное отличие таких строк от String -строк: это обычный массив, размер которого известен заранее и не меняется в процессе работы. Можно объявить строку как массив и посимвольно задать текст:
Такой вариант записи не очень удобный, поэтому строки в C/C++ можно задавать просто текстом в двойных кавычках – компилятор сам посчитает размер массива:
Полученный выше массив содержит 6 символов: 5 на слово hello и 1 на завершающий символ. Текст в данном массиве можно изменять в процессе работы программы, потому что с точки зрения программы мы создали обычный массив и заполнили его буквами. Изменим первую букву на прописную: str[0] = ‘H’; . Выведем в монитор порта:
Serial умеет работать с такими данными и с радостью их выведет.
Объявление как указатель
Также строку можно объявить как указатель на const char* – то есть сам текст в кавычках хранится где то в программе, а мы получаем на него “ссылку”:
Текст в такой строке менять уже нельзя, но можно использовать дальше в программе для сложения или вывода:
Оптимизация
Компилятор оптимизирует строковые константы, но не во всех случаях.
Если создать несколько строк как массивы (которые можно изменять) и присвоить им одинаковые строки, то они займут место в памяти как разные строки, т.е. столько, сколько в них суммарно символов:
Если создать несколько одинаковых строк как указатели – то компилятор их оптимизирует и они займут место в памяти как одна строка!
Если при выводе в Serial или передаче в другие функции мы используем одинаковые строки, то они также будут оптимизироваться и занимать место как одна строка:
В то же время F() – строки (подробнее в уроке про PROGMEM) не оптимизируются компилятором и занимают в программной памяти каждая своё место:
Сложение компилятором
Си-строки можно складывать из нескольких строк через пробелы:
И переносить сложение на новую строку:
Сложение происходит на этапе компиляции, то есть скомпилированной программе это будет одна большая строка.
Отличия от String
В отличие от String-строк, Си-строки:
Для этого существуют специальные функции, о которых мы поговорим ниже.
Длина строки
Для определения длины текста можно использовать оператор strlen() , который возвращает количество символов в строке. Сравним его работу с оператором sizeof() :
Здесь оператор sizeof() вернул количество байт, занимаемое массивом. Массив я специально объявил с размером бОльшим, чем содержащийся в нём текст. А вот оператор strlen() посчитал и вернул количество символов, которые идут с начала массива и до нулевого символа в конце текста без его учёта. А вот такой будет результат при инициализации без указания размера массива:
Массив строк
Можно создать один массив с несколькими строками и обращаться к ним по индексу, фактически это будет двухмерный массив. Выглядит следующим образом:
Таким образом удобно паковать строки для создания текстовых меню и прочего. Единственный большой минус – весь этот текст висит в оперативной памяти мёртвым грузом. Можно сохранить его во Flash – программной памяти (PROGMEM), об этом читайте в отдельном уроке.
Оптимизация памяти
Как я писал выше – “текст в кавычках” хранится и в памяти программы, и в оперативной памяти, то есть после запуска микроконтроллера строка загружается в оперативную память, и уже там мы имеем к ней доступ. Как правило, объём программной памяти микроконтроллера в несколько раз больше, чем оперативной. Есть несколько возможностей хранения строк только в программной памяти, об этом очень подробно поговорим в уроке про PROGMEM.
Инструменты для Си-строк
Есть готовые функции, позволяющие конвертировать различные типы данных в строки:
- itoa(int_data, str, base) – записывает переменную типа int int_data в строку str с базисом* base.
- ltoa (long_data, str, base) – записывает переменную типа long long_data в строку str с базисом* base.
- ultoa (unsigned_long_data, str, base) – записывает переменную типа unsigned long unsigned_long_data в строку str с базисом* base.
- dtostrf(float_data, width, dec, str) – записывает переменную типа float float_data в строку str с количеством символов width и знаков после запятой dec.
* Примечание: base – основание системы счисления, тут всё как при выводе в Serial:
- DEC – десятичная
- BIN – двоичная
- OCT – восьмеричная
- HEX – шестнадцатеричная
И наоборот, можно преобразовывать строки в численные данные, функция вернёт результат:
- atoi(str) – преобразование str в int
- atol(str) – преобразование str в long
- atof(str) – преобразование str в float
2 кБ Flash памяти!! Максимально избегайте их применения в крупном проекте. Для преобразования можно сделать свою функцию, практически готовые варианты для всех типов данных можно найти в стандартной ардуиновской Print.cpp (ссылка на файл на гитхабе Arduino).
Массивы символов не так просты, как кажутся: их возможности сильно расширяет стандартная библиотека cstring. Использование всех доступных фишек по работе с массивами символов позволяет полностью избавить свой код от тяжёлых String-строк и сделать его легче, быстрее и оптимальнее. Подробно обо всех инструментах можно почитать в официальной документации. Очень интересный пример с манипуляцией этими инструментами можно посмотреть здесь. А мы вкратце рассмотрим самые полезные.
Важный момент: библиотека работает со строками как с указателями, и многие функции возвращают как результат именно указатель. Как это понимать, если вы не читали урок про указатели и/или тема слишком сложная? Указатель – первый символ в строке, работа со строкой начнётся с него. Последним символом является нулевой символ, и для программы строка существует именно в этом диапазоне. Если какая-то функция возвращает указатель на конкретный символ в строке – по сути она возвращает часть строки, начиная с этого символа и до конца строки. Например, мы искали символ , в строке «Hello, world!» . Программа вернёт нам указатель на эту запятую, по сути это будет кусочек той же самой строки, содержащий «, world!» . Просто “начало” строки сместится.
Копирует str2 в str1, включая NULL . Так как мы передаём указатель, цель и место назначения можно “подвинуть”:
Копирует num символов из начала str2 в начало str1
Библиотека
У меня есть библиотека для работы с Си-строками: их преобразования и парсинга на блоки данных. Некоторые инструменты реализованы гораздо эффективнее, чем в стандартной строковой библиотеке. Библиотека называется GParser, документацию и примеры смотрите на GitHub.