Close

printf() + PSTR() + %S And INCREASED code-size???

A project log for AVR Random Potentially-Obsure Potentially-Usefuls

Random potentially-obscure potentially-useful things related to AVRs

eric-hertzEric Hertz 08/27/2016 at 19:122 Comments

E.G.

printf("The variable 'thing' is %s.\n",
            ( thing ) ? "true" : "false");
And, yahknow, with AVR's it's smart to use PSTR() and printf_P():
printf_P(PSTR("The variable 'thing' is %s.\n"),
            ( thing ) ? "true" : "false");
But, then... What about the strings "true" and "false"?

They're still stored in RAM, right? They're certainly not *explicitly* PSTR()ed, here...

So some searching, and I figured it had to be possible, but couldn't guess... found it as a side-note on a forum about something else entirely.

%S (capital S):

printf_P(PSTR("The variable 'thing' is %S.\n"),
            ( thing ) ? PSTR("true") : PSTR("false"));
(FYI: coulda just checked 'man printf_P'... It's a bit difficult to find in there, as it's way down there... And, no mention of PSTR, so search instead for "ROM")

BUT!

I did something *just like this* and it actually *increased* my .text size by eight bytes, while making Zero impact on .bss and .data!

Can't exactly explain it... maybe the optimizer was too smart for it's own good?

So, if you're tight on space, be sure to check your savings when doing something like this...


If anyone cares to verify my findings, here's the actual code-snippet:

#if 0
      sprintf_P(stringBuf, PSTR("%s %"PRIu16" <-- %" PRIu8 "\n\r"),
               (rowNCol) ? "row" : "col",
               addr, highBit);
#else
      //No decrease in .data/.bss, increased .text from 8152 to 8160!
      sprintf_P(stringBuf, PSTR("%S %"PRIu16" <-- %" PRIu8 "\n\r"), 
               (rowNCol) ? PSTR("row") : PSTR("col"),
               addr, highBit);
#endif
$ avr-gcc -v
Using built-in specs.
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/4.8.1/lto-wrapper
Target: avr
Configured with: ../src/configure -v --enable-languages=c,c++ --prefix=/usr/lib --infodir=/usr/share/info --mandir=/usr/share/man --bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-libssp --build=i486-linux-gnu --host=i486-linux-gnu --target=avr
Thread model: single
gcc version 4.8.1 (GCC)


Discussions

James Newton wrote 08/30/2016 at 18:42 point

I would assume the size of the pointer (the address in FLASH) to the string is larger than the string itself. If your strings where "This is absolutely TRUE!!!" and "False! FALSE! How could you say that!?" then my guess is you would see a savings with PSTR().

Of course, that doesn't explain the segment size changes... that is weird... 

  Are you sure? yes | no

Eric Hertz wrote 08/31/2016 at 04:46 point

Good point about address-sizes... 4+ bytes seems large for a 16-bit flash-address-space, but it's possible, especially considering there are AVRs with 128+kB of flash, which, as I recall, requires use of an additional bit in a register (ramp?). Plausible the _P functions and PSTR() are general-purpose enough to handle that case, as well.

The only thing I can think of regarding the lack in change-of-size of .bss and .data are that maybe "row" and "col" have been used elsewhere, and the optimizer was smart enough to recognize these as unchanging (and identical) so (before PSTR()) reused the same RAM location... plausible, 

I suppose. I could, maybe, do a *really* simple test and look at the assembly output.

  Are you sure? yes | no