0

For example, for the dummy function write(int length, const char* text){...}, is there any difference in terms of memory between these two approaches?

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

or

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

Bonus: what if there's some repetition? i.e. A loop calls the function repeatedly using an array whose elements are the intended arguments.

I'm asking this question, especially the bonus, in hopes of better understanding how each consumes memory to optimize my efficiency when writing on memory-sensitive platforms like Arduino. That said, if you know of an even more efficient way, please share! Thanks!

larsima
  • 19
  • 1
  • 4
  • 2
    Do not fool yourself, this does not make optimization. Algorithms make optimization. Do whatever is most readable for your program. – DeiDei Jun 10 '18 at 20:57
  • 4
    put both into godbolt.org, enable optimisations and see if there are any differences (there probably wont be) – Alan Birtles Jun 10 '18 at 20:57
  • Without more context, I'd expect [the As-If rule](https://stackoverflow.com/questions/15718262/what-exactly-is-the-as-if-rule) to kick in and make them the same. – user4581301 Jun 10 '18 at 21:27

1 Answers1

2

It depends on whether char txt[19] is declared in scope of a function or at a global (or namespace) scope.

If in scope of a function, then txt will be allocated on the stack and initialized at run time from a copy of the string literal residing in a (read-only) data segment.

If at global scope, then it will be allocated at build time in the data segment.

Bonus: if it's allocated in some sub-scope, like a loop body, then you should assume it will be initialized during every loop iteration (the optimizer might do some tricks but don't count on it).

Example 1:

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

Here len (an int) and txt (19 bytes + alignment padding) will be allocated in the program's data segment at build time.

Example 2:

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

Here the string literal "The cake is a lie." will be allocated in the program's data segment at build time. In addition, len and txt (19 bytes + padding) may be allocated on the stack at run time. The optimizer may omit the len allocation and maybe even txt, but don't count on it, as it's going to depend on many factors, like whether write body is available, what it does exactly, the quality of the optimizer, etc. When in doubt, look at the generated code (godbolt now supports AVR targets).

Example 3:

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

Here the string literal "The cake is a lie." will be allocated in the program's data segment at build time. The 18 will be embedded in the program code.


Since you're developing on AVR, there are some additional specifics worth mentioning, namely the application's executable is initially stored in the Flash, and once you "run" it, it is copied to the RAM. It is possible to avoid copying to RAM and keep the data in the Flash using the PROGMEM keyword (though to do anything meaningful with the data you will need to copy it to RAM).

rustyx
  • 80,671
  • 25
  • 200
  • 267
  • I think I understand what you're saying, but how does this compare to writing the argument values in-line of the function call (like "write(18,"The cake is a lie.")")? How does writing arguments in that fashion impact memory compared to what you described? – larsima Jun 11 '18 at 18:18
  • @ChrisKuhn It does not impact memory consumption, because both int len and chat txt(which is a pointer to a character array in data section) are allocated in stack memory space. By allocation it is meant that stack pointer is moved some bytes to make room for them. – Soumen Jun 13 '18 at 11:23
  • Never forget the as-if-rule. If the compiler is good enough, and the two examples are actually functionally identical, they should result in the same code. – Deduplicator Jun 13 '18 at 12:27