• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

где делать объявление локальных переменных

enjoynering

Well-known member
Мучает впорс по оптимизации памяти. Как мы все знаем в МК есть стек (stack) и куча(heap). Стек для глобальных переменных и сним ПОКА впросов нет. А вот куча которая используется для локальных переменных, находящихся внутри различных функций, не дает мне спать.

Вот пример кода для затравки

Код:
void webTest()
{
  bool    changed = false;
  String  load    = " ";

  Serial.println("\r\nrequest TEST");
  float x = 345.345/345.567;

  load = WebServer.arg("module");
  if (load.length() > 0)
 {
   changed = true
 }
Здесь мы объявили переменные changed и load в начале функции. Вопрос первый: changed имеет размерность одни байт, но ESP8266 у нас 32 битный. Зачит ли это что для changed в куче выделится 32 бита? Впрос второй: как мы знаем переменные типа String - это безразмерный Array типа Char. Я инициализировал load c пробелом. Значит в куче под него будет 1 байт. Потом мы выделил в куче место под float x. По идее оно должно встать в куче сразу за пробелом? Потом я начинаю принимать в load данные от сервера которые уже например 20 байт. Как поведет себя куча в этом случае если у меня до этого под load выделилось всего 1 байт?

Не лучше бы сделать так?

Код:
void webTest()
{
  bool    changed = false;

  Serial.println("\r\nrequest TEST");
  float x = 345.345/345.567;

  String load = WebServer.arg("module");
  if (load.length() > 0)
  {
   changed = true
  }
Заранее спсибо.
 

Юрий Ботов

Moderator
Команда форума
1. В микроконтроллере нет ни стэка ни кучи. У него есть RAM и как ее распредилить - ваша забота.
2. Стэк и куча это изначально части модели памяти языка С и его потомков. Разница в том что распределение и освобождение памяти в стэке автоматическое, но при помощи его в С сложно(хоть и можно) разместить массивы, строки или другие сложные объекты. Кроме того выделение памяти в стэке не контролируется, и можно не глядя затереть что нибудь нужное или вызвать исключение защиты памяти.
Распределение/освобождение из кучи (heap) происходит с использованием alloc/free и можно проконтролировать дали тебе память или нет, что безопаснее для больших объектов.
3. Все локальные переменные функций С-подобные языки хранят в СТЭКЕ. Если объект большой - то в стэке хранится ссылка на объект который сам засовывается в кучу.
У вас в webTest:
changed (имеет размерность 1 БИТ) - кладется в стэк занимая 32 бита. (если битовых переменных несколько хороший компилятор положит их в одно 32 разрядное слово)
load (ссылка на объект String) кладется в стэк, сам объект String " " кладется в кучу, кроме пробела и 0 символа туда кладутся еще несколько параметров объекта типа "String". Не путайте объект String и массив символов char* ЭТО АБСОЛЮТНО РАЗНЫЕ ВЕЩИ.
x - кладется в стэк

Вообще в C при вызове функции кладутся:
- передаваемые параметры в порядке поступления
- адрес возврата
- локальные переменные функции
при этом указатель стэка внутри функции указывает на адрес возврата.

Теперь понятно почему я не отвечаю конкретно на ваш вопрос?
 
Последнее редактирование:
Сверху Снизу