Использование static в классе
- Войдите на сайт для отправки комментариев
Пт, 28/10/2016 - 11:58
Здравствуйте!
Прочитал что в С/С++ можно использовать одну переменную на все объекты полученные от одного класса.
static int count = 0;
По сути проблема в том, что мне не хватает ОЗУ при создании множества объектов и некоторые переменные я хочу "объединить". Например
class ClassTimeInterval { private: RTC_DS1307 rtc1; static DateTime timeNow;
...
Но не работает.
Вобще доступно ли такое на Ардуино? Может я не правильно прописываю?
А выделить память под статическую переменную не пробовал?
DateTime
ClassTimeInterval::
timeNow;
Думаю, что проблема в том, о чём написал коллега Andy, но на всякий случай спрошу: "А что значит "не работает""? В чём это выражается?
В ардуине static работает по полной, как повелевает стандарт и воплощает GCC. Никакой специфики. Давайте полній код и вывод ошибки - чего подскажем.
В ардуине static работает по полной, как повелевает стандарт и воплощает GCC. Никакой специфики. Давайте полній код и вывод ошибки - чего подскажем.
он же дал код - как у него не компилится, как я дал - должно... по крайней мере у меня в титановом велосипеде только константы желают быть статическими
Может я не понял, но DateTime timeNow; у меня не константа, она постоянно получает значение текущего времени.
Вот ошибка, количество ошибок по количеству созданых объектов:
ClassTimeIntervalNew\ClassTimeIntervalNew.cpp.o: In function `ClassTimeInterval::getStatusPWM()':
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew/ClassTimeIntervalNew.cpp:213: undefined reference to `ClassTimeInterval::timeNow'
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew/ClassTimeIntervalNew.cpp:213: undefined reference to `ClassTimeInterval::timeNow'
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew/ClassTimeIntervalNew.cpp:214: undefined reference to `ClassTimeInterval::timeNow'
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew/ClassTimeIntervalNew.cpp:214: undefined reference to `ClassTimeInterval::timeNow'
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew/ClassTimeIntervalNew.cpp:214: undefined reference to `ClassTimeInterval::timeNow'
ClassTimeIntervalNew\ClassTimeIntervalNew.cpp.o:C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew/ClassTimeIntervalNew.cpp:281: more undefined references to `ClassTimeInterval::timeNow' follow
collect2.exe: error: ld returned 1 exit status
Ошибка компиляции.
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew\ClassTimeIntervalNew.cpp: In member function 'byte ClassTimeInterval::getStatusPWM()':
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew\ClassTimeIntervalNew.cpp:213:10: error: passing 'const DateTime' as 'this' argument of 'DateTime& DateTime::operator=(const DateTime&)' discards qualifiers [-fpermissive]
timeNow = rtc1.now();
^
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew\ClassTimeIntervalNew.cpp: In member function 'float ClassTimeInterval::calcPwmUp()':
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew\ClassTimeIntervalNew.cpp:281:10: error: passing 'const DateTime' as 'this' argument of 'DateTime& DateTime::operator=(const DateTime&)' discards qualifiers [-fpermissive]
timeNow = rtc1.now();
^
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew\ClassTimeIntervalNew.cpp: In member function 'float ClassTimeInterval::calcPwmDown()':
C:\Users\Константин\Documents\Arduino\libraries\ClassTimeIntervalNew\ClassTimeIntervalNew.cpp:288:10: error: passing 'const DateTime' as 'this' argument of 'DateTime& DateTime::operator=(const DateTime&)' discards qualifiers [-fpermissive]
timeNow = rtc1.now();
^
Ошибка компиляции.
orcsin,
Если Вы хотите пользоваться статическими переменными класса, то сначала почитайте как это делается.
Во-первых, переменную нужно описать, т.е. выделить по неё память (см. пост Andy).
Во-вторых, обращаться к ней надо либо указывая имя класса
или через любой экземпляр, но всегда помните, что она (эта переменная) одна на все экземпляры.
Ну не видя всего кода можна предположить наличие отсутствия DateTime ClassTimeInterval::timeNow;
Так а где мне объявить - DateTime ClassTimeInterval::timeNow;
В test.h или в test.ino?
ino
В *.ino :)
Всем спасибо за помощь!!!
Программа вроде не большая, ещё не всё что хотел написал, а ОЗУ уже заканчивается. Пытался писать правильно, объяляю всякие переменные, а теперь не хватает памяти :(
Sketch uses 21 770 bytes (70%) of program storage space. Maximum is 30 720 bytes.
Global variables use 1 747 bytes (85%) of dynamic memory, leaving 301 bytes for local variables. Maximum is 2 048 bytes.
Low memory available, stability problems may occur.
Это сколько же "всяких переменных" надо объявить, чтобы израсходовать более полутора килобайт памяти...
Могу предположить, что Ваши переменные, которые забивают память, - это текстовые константы. Если так, их можно оставить в PROGMEM, не копируя в оперативную память.
Автор хочет побить рекорд Тойоты в 11000 переменных?
Наверное просто массивы большие.
Да есть большие массивы для меню. У меня древоводное меню на 20 листов.
Вот все глобальные переменные, если что подскажите как сократить, буду благодарен :)
И вот ещё моя либа:
плюс я так понимаю жрут общие библиотеки:
Это только глобальные переменные.
Но надо ещё будет дописать кое что из функционала...
matrixMenu сразу в PROGMEM - и 225 байт ОЗУ свободны. Остальные большие массивы туда же. Либы тоже под плдозрением, каждую препарировать индивидуально - исключаете на время из проекта, коментируете обращения к ней чтоб скетч собрался и смотрите как её отсутствие скажется на используемой памяти. Возвращаете и переходите к следующей. Выводы в конце. Кстати, результатами здесь можете поделится.
Logik, классная штука, но только я не понял, какую память он жрёт и сколько её в наличии и осталось.
Перевёл большой массив в PROGMEM получил до и после:
/* Sketch uses 21 818 bytes (71%) of program storage space. Maximum is 30 720 bytes.
Global variables use 1 747 bytes (85%) of dynamic memory, leaving 301 bytes for local variables.
Maximum is 2 048 bytes */
/* Sketch uses 21 820 bytes (71%) of program storage space. Maximum is 30 720 bytes.
Global variables use 1 523 bytes (74%) of dynamic memory, leaving 525 bytes for local variables.
Maximum is 2 048 bytes */
Освободил 224 байта в ОЗУ, но во флеше прибавилось только 2 байта
Ну переменные бывают разные. Среди них бывают как ни странно константы. Ладно если бы те которые в программе сидят, и программисты выбирают под конечные ситуации. Так есть константы которые подбираются пользователем. Скорее из-за них и городится меню. Но если процедурное программирование обходится минимумом переменных, то объектное генерирует их как бы не по максимуму. Но если в больших что ОЗУ под код что ОЗУ под данные одно и тоже. То здесь это разные вещи-флеш память и ОЗУ. Про еепром я не говорю. Это даже не ОЗУ.
Мой совет . Определитесь что делать переменными, а что делать константами. Ну и что будет константами которые переменные, но меняются через меню.
ПС:https://goo.gl/vASyD5
А enum что сразу кладёт данные во флешь?
А enum что сразу кладёт данные во флешь?
У меня подозрение, что enum это просто формат данных. В коде это всего навсего байт.
qwone, не много вас не понял...
Все глобальные переменные я привёл выше, других больше нет.
Констант, кроме масивом меню у меня нет. #define вроде тоже не занимаю ОЗУ.
Вобщем пока только за счёт ... получилось уменьшить расход ОЗУ:
Было:
Sketch uses 21 770 bytes (70%) of program storage space. Maximum is 30 720 bytes.
Global variables use 1 747 bytes (85%) of dynamic memory, leaving 301 bytes for local variables. Maximum is 2 048 bytes.
Low memory available, stability problems may occur.
Стало:
Sketch uses 21 778 bytes (70%) of program storage space. Maximum is 30 720 bytes.
Global variables use 1 467 bytes (71%) of dynamic memory, leaving 581 bytes for local variables. Maximum is 2 048 bytes.
Чувствительно, но мало :(
ок. а, зачем это хранить так
byte
matrixMenu[45][5] = {
// {Номер меню, родительское меню, дочернее меню, Х_курсор, Y_курсор}; menu
а, не так?:
У каждого меню свои значения этих констант.
надо написать 45 раз.
и т.д. точнее это кодировка позиции курсора в меня. Сложно получилось, но пока ни чего попроще не получается.
ПРикол в том, что у меня на разных страницах меню, разные позиции курсоров, поэтому приходится каждую страницу программировать отдельно
ну да экран 16 на 2 это большой размер. 32 позиции. Глядишь уже одна координата пропала.
х=pos%16;
y=pos/16;
а так еще проще
lcd.setCursor(pos%16,pos/16);
х=pos%16;
y=pos/16;
а так еще проще
lcd.setCursor(pos%16,pos/16);
В данном контроллере нет аппаратной команды деления, а потому и деление, и взятие остатка - программные операции. Поэтому, есл нужно и то, и другое, то лучше использовать функцию div. Тогда функция деления будет исполянться один раз, а не два, как у Вас.
Logik, классная штука, но только я не понял, какую память он жрёт и сколько её в наличии и осталось.
...
Освободил 224 байта в ОЗУ, но во флеше прибавилось только 2 байта
Если у Вас в программе есть предопределенные константы, они обязательно должны где-то храниться.
Если Вы их просто описываете в тексте программы, они записываются в PROGMEM, а перед началом работы (после включения питания) переписываются в OЗУ. Если Вы при описании массива исплоьзуете PROGMEM, то они там и остаются, а в ОЗУ не копируются. Соответственно, места там не занимают. Но в PROGMEM они остаются в любом случае.
х=pos%16;
y=pos/16;
а так еще проще
lcd.setCursor(pos%16,pos/16);
В данном контроллере нет аппаратной команды деления, а потому и деление, и взятие остатка - программные операции. Поэтому, есл нужно и то, и другое, то лучше использовать функцию div. Тогда функция деления будет исполянться один раз, а не два, как у Вас.
Этот совет касается оптимизации, и мне кажется, об этом нужно писать, т.к. в подавляющем большинстве случаев это несущественно. В частности - несущественно с точки зрения экономии оперативной памяти, о чем спрашивает ТС. Кроме того, в данном случае совет вредный: деление на степени двойки реализуется сдвигами. Это в любом случае лучше вызова функции.
2 ЕвгенийП Не понял на счет процессора. Но логические операции и сдвиг должен быть.
х=pos&15;
y=(pos>>4)&1;
а так еще проще
lcd.setCursor(pos&15,(pos>>4)&1);
ПС: Просто упаковать плотнее данные и весь секрет.
ну да экран 16 на 2 это большой размер. 32 позиции. Глядишь уже одна координата пропала.
х=pos%16;
y=pos/16;
а так еще проще
lcd.setCursor(pos%16,pos/16);
Совсем не понял, можно чуть подробнее, пожалуйста.
В одном байте восем бит. х-х-х-х-х-х-х-х , где х это 0 или 1. в один байт можно записать число от 0 до 255. у вас позиций на курсоре 2*16=32 . И можно Хкур и Yкур упаковать в один байт х-х-х-Yкур-Хкур-Хкур-Хкур-Хкур . Ну а дальше просто извлечение этих значений.
int
timeLightTimer[4][2][2][2] = {};
// удалить позже
это звучит гордо!
Наверное я убогий, никогда такие массивы не были нужны. 4 уровня - это круто!
Удалить позже статчиеский массив это "прикольно|.
kisoft, вы попонтоваться или посоветовать что то полезное?
В одном байте восем бит. х-х-х-х-х-х-х-х , где х это 0 или 1. в один байт можно записать число от 0 до 255. у вас позиций на курсоре 2*16=32 . И можно Хкур и Yкур упаковать в один байт х-х-х-Yкур-Хкур-Хкур-Хкур-Хкур . Ну а дальше просто извлечение этих значений.
Примерно понял, но я так понимаю это будет плохо читаемо? Так я вижу координат в явном виде, а в вашем случае наверное нет.
Примерно понял, но я так понимаю это будет плохо читаемо? Так я вижу координат в явном виде, а в вашем случае наверное нет.
Вот я это хотел услышать! Проблемы в программах у программистов связаны не с программами, а проблемами с мозгами этих программистов. Вот вы привыкли, что памяти много, и вы не умеете не только читать экономные программы, но и писать их. У вас два пути или искать более мощные компьютеры или учится читать и писать такие программы. Это не в обиду к вам. Просто ваш код вас научит, или не научит. Программирование это все-таки практика.
не буду создавать новую тему, поэтому спрошу тут:
У меня есть 4 канала света по 2 рабочих интервала и я создаю объекты вот так:
Для всех 4 каналов(quantityColor) значения приватных переменных в классе
одинаковые для обоих интервалов(quantityInterval).
Считываю я эти значения с первого интервала ColorLightInterval[quantityColor][0], а вот записывать прийдётся в оба, можно как то эти два значения объединить, может через ссылку, но класс создаёт массив объектов и ему без разницы это массив [4][2] или [8].
Есть какие то мысли?
Примерно понял, но я так понимаю это будет плохо читаемо? Так я вижу координат в явном виде, а в вашем случае наверное нет.
Вот я это хотел услышать!
я не хотел, но услышал - что препятствует запустить виндовый калькулятор в режиме "Программист"?
Примерно понял, но я так понимаю это будет плохо читаемо? Так я вижу координат в явном виде, а в вашем случае наверное нет.
Вот я это хотел услышать! Проблемы в программах у программистов связаны не с программами, а проблемами с мозгами этих программистов. Вот вы привыкли, что памяти много, и вы не умеете не только читать экономные программы, но и писать их. У вас два пути или искать более мощные компьютеры или учится читать и писать такие программы. Это не в обиду к вам. Просто ваш код вас научит, или не научит. Программирование это все-таки практика.
Свою программу я почти написал, теперь в принципе и занимаюсь оптимизацией кода, что то вычитал новое и начию переписывать код переодически. До этого как то не понимал классы, а потом попалась хорошая книжка и всё стало понятно и стал переписывать массивы не понятных данных в классы и т.д. Вот теперь про PROGMEM знаю :) Чуть помогло.
В одном байте восем бит. х-х-х-х-х-х-х-х , где х это 0 или 1. в один байт можно записать число от 0 до 255. у вас позиций на курсоре 2*16=32 . И можно Хкур и Yкур упаковать в один байт х-х-х-Yкур-Хкур-Хкур-Хкур-Хкур . Ну а дальше просто извлечение этих значений.
А можно пример кодировки моих координат, то что вы написали выше, так сказать для закрепления, например:
Хотя мне кажется что когда я вижу 7,1, я могу понять где находится курсор, но если там будет цифра например 01010111 или 12, я конечно может выучу со временем коды всех 32 позиций, но с наскока такое будет трудно понять...
Примерно понял, но я так понимаю это будет плохо читаемо? Так я вижу координат в явном виде, а в вашем случае наверное нет.
Вот я это хотел услышать!
я не хотел, но услышал - что препятствует запустить виндовый калькулятор в режиме "Программист"?
Не сильно удобно понимать все значения через калькулятор, когда у тебя 45+ таких значений. А если нужно увидеть общую картину всех значений, то мне кажется это вобще ужас...
Оптимизация штука нужная и полезная, но иногда мне кажется прозрачность кода лучше :)
А то через месяц хрен поймёшь что написал :)
Не сильно удобно понимать все значения через калькулятор, когда у тебя 45+ таких значений. А если нужно увидеть общую картину всех значений, то мне кажется это вобще ужас...
мне не понятно, откуда у тебя, вообще, эта картина берётся, если должно быть
как я писал выше. что за чехарда там у тебя с курсором - забыл курсор в одном месте, вернулся взад - курсор у тебя не в начальной позиции, а чёрти где?
А можно пример кодировки моих координат, то что вы написали выше, так сказать для закрепления, например:
Хотя мне кажется что когда я вижу 7,1, я могу понять где находится курсор, но если там будет цифра например 01010111 или 12, я конечно может выучу со временем коды всех 32 позиций, но с наскока такое будет трудно понять...
Опять вы меня не поняли в lcd.setCurcor(7,1); нет расхода памяти. А вот в lcd.setCurcor(matrixMenu[i][4],matrixMenu[i][5]); уже есть . то есть matrixMenu есть лишняя колонка. И сокращать надо так lcd.setCurcor(matrixMenu[i][4]%16,matrixMenu[i][4]/16); И ничего помнить не надо. Оптимизация идет не только ради оптимизации, но и удобства программирования. Разве, что кострукция выражений усложнилась. Так и в русском языке. Есть же простые предложения, но на деле приходим к большим и сложным.
----
...но если там будет цифра например 01010111 или 12, я конечно может выучу со временем коды всех 32 позиций...
Вы привыкли пользоваться десятичной системой?
Сколько чисел можно представить в десятичной системе? Миллон? Ммиллиард? Болше?
Вы всерьез утверждаете, что их все Вы выучили?
Не сильно удобно понимать все значения через калькулятор, когда у тебя 45+ таких значений. А если нужно увидеть общую картину всех значений, то мне кажется это вобще ужас...
мне не понятно, откуда у тебя, вообще, эта картина берётся, если должно быть
как я писал выше. что за чехарда там у тебя с курсором - забыл курсор в одном месте, вернулся взад - курсор у тебя не в начальной позиции, а чёрти где?
Вот сруктура меню, стрелочки перехода в гугл док исчезли. Берюзовые клетки с ">" это возможные положения курсора
https://docs.google.com/spreadsheets/d/1WP253M536Bz-2Sz5sBUCzdEJT4MSMXNe...
а массив
это координаты каждого положения курсора и пути вверх и вниз для этого положения.
Где то же мне это нужно хранить. Пока ни чего лучшего в голову мне не пришло, если подскажите - буду благодарен.
Опять вы меня не поняли в lcd.setCurcor(7,1); нет расхода памяти. А вот в lcd.setCurcor(matrixMenu[i][4],matrixMenu[i][5]); уже есть . то есть matrixMenu есть лишняя колонка. И сокращать надо так lcd.setCurcor(matrixMenu[i][4]%16,matrixMenu[i][4]/16); И ничего помнить не надо. Оптимизация идет не только ради оптимизации, но и удобства программирования. Разве, что кострукция выражений усложнилась. Так и в русском языке. Есть же простые предложения, но на деле приходим к большим и сложным.
Я правильно понял, что для lcd.setCurcor(7,1) matrixMenu[i][4] = 16+7=23 ?
Тогда 23%16 = 7, а 23/16 = 1 ?
Я правильно понял, что для lcd.setCurcor(7,1) matrixMenu[i][4] = 16+7=23 ?
Тогда 23%16 = 7, а 23/16 = 1 ?
Ну да 23%16 = 7 (остаток от деления 23 на 16 равно 7. А целая часть 23/16 равна 1.
Что бы вам понятнее было 23%10 будет 3 (остаток от деления на 10). А вот 23/10 будет 2. 0.3 усечется так как позиция (int)
ПС: 23=0х17=B00010111 . Все это одно и то же число. только первое в десятичном, второе в шеснадцатиричном а третье в двоичном.
lcd.setCurcor(7,1) можно записать так lcd.setCurcor(0х17%0х10,0х17/0х10) . где вместо 0х17 можно почтавить ячейку из matrixMenu[i][4]
ППС : 16=0х10=B00010000 . Это что бы тупых вопросов не было.