Выделение памяти указателя в функции

Я хотел бы знать, как Arduino выделяет память для указателей в аргументах функций.

Например. У меня есть этот код, который использует 192 байта (компилятор Arduino IDE: Глобальные переменные используют 192 байта (9%) динамической памяти).

char alph [] = {'a', 'b', 'c','\0'}; // 4 bytes
int numb [] = {1, 2, 3, 4}; // 8 bytes
float flo [] = {1.1, 2.2, 3.3}; // 12 bytes

void fn(){
  Serial.println(alph);
  Serial.println(numb[1]);
  Serial.println(flo[1]);
}

void setup()
{
  Serial.begin(9600);
  fn();
}

void loop(){}

Следующий код такой же, как и выше, но я использую указатель на переменные в аргументах, которые используют 234 байта (компилятор Arduino IDE: Глобальные переменные используют 234 байта (11%) динамической памяти).

char alph [] = {'a', 'b', 'c','\0'}; // 4 bytes
int numb [] = {1, 2, 3, 4}; // 8 bytes
float flo [] = {1.1, 2.2, 3.3}; // 12 bytes

void fn(char * _alph, int * _numb, float * _flo){
  Serial.println(_alph);
  Serial.println(_numb[1]);
  Serial.println(_flo[1]);
}

void setup()
  Serial.begin(9600);
  fn(alph, numb, flo);
}

void loop(){}

Существует разница в 42 байта для использования трех указателей. Почему? Указатель на символ равен 1 байту, указатель int равен 2 байтам, а указатель с плавающей точкой имеет длину 4 байта. Должна ли разница составлять 7 байт?

, 👍0

Обсуждение

Я делаю это 224, а не 234. Однако вы забываете одну простую вещь: компилятор умен., @Majenko

Кстати: все указатели имеют размер 2 байта, независимо от того, на что они указывают., @Majenko

Они используют 192 и 224 байта оперативной памяти. Я могу уменьшить 224 до 192 для второго скетча, добавив ключевое слово "const" перед всеми тремя объявлениями массива. Ключевое слово "const" дает компилятору больше возможностей делать умные вещи., @Jot

Но если добавить 'const' к массивам, я не смогу изменить его динамически, @Mario J.

Если вы хотите узнать, что происходит, вам придется посмотреть на ассемблерный код, который создает компилятор., @Gerben

*Указатель char равен 1 байту, указатель int - 2 байтам, а указатель float-4 байтам.* - Нет, указатель char равен 1 байту, указатель int-2 байтам, а указатель float-4 байтам. Однако указатель *** * всегда равен 2 байтам., @Nick Gammon


1 ответ


1

Когда вы спрашиваете: "Почему?". Самый дешевый ответ: "почему бы и нет?".

Компилятор может выполнять умные оптимизации, как писал @Majenko. Вот в чем дело.

Даже для такого небольшого скетча у компилятора есть множество методов оптимизации на выбор. Изменение одной строки или добавление переменной может заставить компилятор выбрать другие варианты оптимизации. Поэтому невозможно связать увеличенное количество байтов с этими дополнительными указателями.

Иногда компилятор может принять решение сохранить переменную в регистре вместо того, чтобы хранить ее в ячейке памяти. Иногда компилятор понимает, что переменная имеет постоянное значение и используется только один раз, тогда компилятор может даже не использовать для нее динамическую оперативную память.

Используемая скетчом динамическая оперативная память еще более тривиальна, поскольку Arduino настраивает компилятор на использование минимального размера кода.

Оптимизировать скетч лучше всего с помощью большого скетча. В вашем небольшом скетче используется последовательная библиотека, и это основная часть скомпилированного кода. Ваши собственные функции и указатели-это просто какой-то код на стороне.

Для начинающих оптимизация компилятора может быть волшебной Абракадаброй. Однако использование массивов не позволит компилятору выполнять экстремальные оптимизации. Возможно, даже найдется логическое объяснение увеличению числа байтов, если изучить ассемблерный код, как написал @Gerben.

,