Оптимизации памяти в коде

k4889
Offline
Зарегистрирован: 10.02.2017

Кто может подсказать по оптимизации памяти в коде ?



Накидал небольшой тестовый скетч меню (пытаюсь  написать свое меню с казино и дамами)



Вопрос 1 - в таком виде глобальные переменные используют 14% памяти, а если убрать строки

currentMenuLVL++ и 

currentMenuNumber[currentMenuLVL]++

то используется уже всего 2% памяти.
Не могу понять почему так и как его можно оптимизировать. Вероятно как-то надо работать со ссылками на объекты, но пока не догнал как.

И вопрос 2 - в структуре используется ссылка на функцию test. Если ее не объявить перед структурой, то появляется сообщение "'test' was not declared in this scope". Такое решение мне кажется не очень красивым, как то можно это обойти ? В примерах ни разу не видел, чтобы функции объявляли перед структурой, а тут IDE ругается (Arduino IDE 1.8.4) 

 

struct structMenu {
 byte Num[3];
 char Name[15]; 
 void (*function)(); 
};

//void test();

struct structMenu mainMenu[] = {
                                {{1,0,0}, "Info",        test},                               
                                {{1,1,0}, "Point 1-1",   test},
                                {{1,1,1}, "Point 1-1-1", test},
                                {{1,1,2}, "Point 1-1-2", test},                               
                                {{1,2,0}, "Point 1-2",   test},
                                {{1,2,1}, "Point 1-2-1", test},
                                {{1,2,2}, "Point 1-2-2", test},
                                {{2,0,0}, "Bloks",       test},                             
                                {{2,1,0}, "Point 2-1",   test},
                                {{2,1,1}, "Point 2-1-1", test},
                                {{2,1,2}, "Point 2-1-2", test},                             
                                {{2,2,0}, "Point 2 - 2", test},
                                {{2,2,1}, "Point 2-2-1", test},
                                {{2,2,2}, "Point 2-2-2", test}
};

byte currentMenuNumber[] = {1,0,0}; // Текущий номер пункта меню (вычисляется динамически)
byte currentMenuLVL;                // Текущий уровень в меню (вычисляется динамически)
byte menuCount;                     // Общее количество пунктов меню (вычисляется динамически)
                                                                   
#define enter 8                                            

void setup() { 
  pinMode(enter, INPUT_PULLUP);
  
  currentMenuLVL = 0; 
  menuCount = sizeof(mainMenu)/sizeof(mainMenu[0]);  
}

void loop() {  
  if (!digitalRead(enter)) {pushButtonEnter();}
}

void test() {return;}

void pushButtonEnter() {    
  for (int i = 0; i < menuCount; i++) 
  {
    if (checkAdress(currentMenuNumber, mainMenu[i].Num)) 
    {
      currentMenuLVL++;
      currentMenuNumber[currentMenuLVL]++;
    }
  }  
}

// Функция проверки соответствия адреса
boolean checkAdress(byte arr1[], byte arr2[]) { 
  boolean checkAdressPosition = true; 
  for (int posNum = 0; posNum < currentMenuLVL; posNum++)
  {      
    if (arr1[posNum] != arr2[posNum]) {checkAdressPosition = false; break;} 
  }
  return checkAdressPosition;
}

 

b707
Offline
Зарегистрирован: 26.05.2017

По вопросу 2 - критерии "красивости" у каждого свои, поэтому в программировании вместо них применяются правила синтаксиса. В этих правилах для языка Си, в частности, говорится, что все переменные, структуры , процедуры и функции должны быть обьявлены до первого использования.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

k4889. Почему надо углублено изучать программистам программирования? Ведь язык Си это не "три блатных аккорда", с помощью которых можно сыграть все. Вот и ваша проблема в том, что вы граничиваетесь "тремя блатными аккордами".

ПС:не эталон, но ознакомится рекомендую #235

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

k4889 пишет:

Вопрос 1 - в таком виде глобальные переменные используют 14% памяти, а если убрать строки

В этом случае Вам массив currentMenuNumber превращается в константу и просто выбрасывается из программы. А вместе выбрасывается и массив mainMenu, потому, что всё, что с этими массивами связано можно посчтать во время компиляции. Вот оптимизатор считает, а массивы выбрасывает.

k4889 пишет:
И вопрос 2 - в структуре используется ссылка на функцию test. Если ее не объявить перед структурой, то появляется сообщение "'test' was not declared in this scope".

Это требования языка программирования. Любая сущность должна быть объявлена ДО использования.

k4889 пишет:
Такое решение мне кажется не очень красивым, как то можно это обойти ? 

Никак.

Некоторые версии IDE сами (вместо Вас) вставляют в начало файла предварительные объявления всех функций. Это не обход - объявление всё равно есть, просто Вы его не видите.

 

k4889
Offline
Зарегистрирован: 10.02.2017

ЕвгенийП пишет:

А вместе выбрасывается и массив mainMenu, потому, что всё, что с этими массивами связано можно посчтать во время компиляции. 

Могут ли в данном случае помочь ссылки на массив ? Просто я с ними не работал и всего не знаю.

ЕвгенийП пишет:

Это требования языка программирования. Любая сущность должна быть объявлена ДО использования.

Это понятно, возможно я не так сформулировал: - Это правильное объявление функции или есть какие-то другие варианты ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

k4889 пишет:

Могут ли в данном случае помочь ссылки на массив ? Просто я с ними не работал и всего не знаю.

В чём помочь? Выбросить массив из памяти? Так если он Вам не нужен - просто выбросьте, а нужен - так как его выбросишь?

k4889 пишет:

Это правильное объявление функции или есть какие-то другие варианты ?

Объявление как объявление.

 

k4889
Offline
Зарегистрирован: 10.02.2017

Спасибо за ответы.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

можно так 

void func();/*объявили*/
void func() { /*описали*/
  Serial.println("Do func");
}
//------main----------------------
void setup() {
  Serial.begin(9600);
  func();/*использовали*/
}

void loop() {
}
/*Скетч использует 1434 байт (4%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 194 байт (9%) динамической памяти, оставляя 1854 байт для локальных переменных. Максимум: 2048 байт.
*/

А можно так

void func();/*объявили*/

//------main----------------------
void setup() {
  Serial.begin(9600);
  func();/*использовали*/
}

void loop() {
}
void func() { /*описали*/
  Serial.println("Do func");
}
/*Скетч использует 1434 байт (4%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 194 байт (9%) динамической памяти, оставляя 1854 байт для локальных переменных. Максимум: 2048 байт.
*/

У структур и классов такая же петрушка