Какая разница (в терминах памяти), если я заранее объявляю аргументы в качестве переменных вместо записи их в строке вызова функции?

Например, для фиктивной функции write(int length, const char* text){...}Есть ли разница в показателях памяти между этими двумя подходами?

write(18,"The cake is a lie.");

или же

int len = 18;
char txt[19] = "The cake is a lie.";
write(len,txt)

Бонус: что если есть какое-то повторение? т.е. цикл вызывает функцию несколько раз, используя массив, элементы которого являются предполагаемыми аргументами.

Я задаю этот вопрос, особенно бонус, в надежде лучше понять, как каждый из них использует память, чтобы оптимизировать мою эффективность при записи на чувствительных к памяти платформах, таких как Arduino. Тем не менее, если вы знаете еще более эффективный способ, пожалуйста, поделитесь! Спасибо!

1 ответ

Это зависит от того, char txt[19] объявляется в области действия функции или в глобальной области (или пространстве имен).

Если в рамках функции, то txt будет размещен в стеке и инициализирован во время выполнения из копии строкового литерала, находящегося в (доступном только для чтения) сегменте данных.

Если в глобальном масштабе, то он будет размещен во время сборки в сегменте данных.

Бонус: если он размещен в какой-то дополнительной области, например в теле цикла, то вы должны предполагать, что он будет инициализироваться во время каждой итерации цикла (оптимизатор может делать некоторые трюки, но не рассчитывать на это).

Пример 1:

int len = 18;
char txt[19] = "The cake is a lie.";
int main() {
    write(len,txt);
}

Вот len (int) а также txt (19 байт + выравнивание выравнивания) будет выделено в сегменте данных программы во время сборки.

Пример 2:

int main() {
    int len = 18;
    char txt[19] = "The cake is a lie.";
    write(len,txt);
}

Здесь строковый литерал "The cake is a lie." будет размещен в сегменте данных программы во время сборки. К тому же, len а также txt (19 байт + заполнение) может быть выделено в стеке во время выполнения. Оптимизатор может опустить len распределение и, возможно, даже txt, но не рассчитывайте на это, так как это будет зависеть от многих факторов, таких как write доступно тело, что именно он делает, качество оптимизатора и т. д. Если есть сомнения, посмотрите на сгенерированный код (теперь Godbolt поддерживает цели AVR).

Пример 3:

int main() {
    write(18,"The cake is a lie.");
}

Здесь строковый литерал "The cake is a lie." будет размещен в сегменте данных программы во время сборки. 18 будет встроен в код программы.


Поскольку вы разрабатываете на AVR, есть некоторые дополнительные особенности, которые стоит упомянуть, а именно, исполняемый файл приложения изначально хранится во Flash, и после того, как вы его "запустите", он будет скопирован в RAM. Можно избежать копирования в ОЗУ и сохранить данные во Flash, используя PROGMEM ключевое слово (хотя, чтобы сделать что-либо значимое с данными, вам нужно будет скопировать их в оперативную память).

Другие вопросы по тегам