首页 > 解决方案 > 如果我提前将参数声明为变量而不是将它们写入函数调用的行内,它有什么区别(在内存方面)?

问题描述

例如,对于 dummy function 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 等内存敏感平台上编写时的效率。也就是说,如果您知道更有效的方法,请分享!谢谢!

标签: c++memory-managementarduinofunction-callsmemory-optimization

解决方案


这取决于是在函数范围内char txt[19]声明还是在全局(或命名空间)范围内声明。

如果在函数范围内,则将在堆栈上分配并在运行时从驻留在(只读)数据段中的字符串文字txt的副本初始化。

如果在全局范围内,那么它将在构建时在数据段中分配。

奖励:如果它被分配在某个子范围内,比如循环体,那么你应该假设它会在每次循环迭代期间被初始化(优化器可能会做一些技巧,但不要指望它)。

示例 1:

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

这里len(an 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."将在构建时分配到程序的数据段中。此外,lentxt(19 字节 + 填充)可能会在运行时在堆栈上分配。优化器可能会忽略len分配,甚至可能会忽略txt,但不要指望它,因为它取决于许多因素,例如writebody 是否可用、它到底做了什么、优化器的质量等。如果有疑问,查看生成的代码(godbolt现在支持 AVR 目标)。

示例 3:

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

在这里,字符串文字"The cake is a lie."将在构建时分配到程序的数据段中。将18嵌入程序代码中。


由于您在 AVR 上进行开发,因此还有一些额外的细节值得一提,即应用程序的可执行文件最初存储在Flash中,一旦您“运行”它,它就会被复制到 RAM 中。可以避免复制到 RAM 并使用PROGMEM关键字将数据保留在 Flash 中(尽管要对数据做任何有意义的事情,您需要将其复制到 RAM 中)。


推荐阅读