30

I have asked a similar question before, but I realize that I can't make heads or tails of the macrology and templateness. I'm a C (rather than C++) programmer.

What does F() actually do? When does it stuff characters into pgmem (flash)? When does it pull characters out of pgmem? Does it cache them? How does it handle low-memory situations?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
iter
  • 4,171
  • 8
  • 35
  • 59
  • 1
    In the previous question, I'm asking where to find the implementation. Having read the source, I realize I fail to understand it. The original question has its full answer, so I accept it. – iter May 17 '13 at 22:35
  • There is also an answer in the [Arduino SE](https://arduino.stackexchange.com/questions/19330/store-string-using-f-macro). – not2qubit Jul 23 '19 at 12:44

2 Answers2

40

There are no templates involved, only function overloading. The F() macro does two things:

  • uses PSTR to ensure that the literal string is stored in flash memory (the code space rather than the data space). However, PSTR("some string") cannot be printed because it would receive a simple char * which represents a base address of the string stored in flash. Dereferencing that pointer would access some random characters from the same address in data. Which is why F() also...

  • casts the result of PSTR() to __FlashStringHelper*. Functions such as print and println are overloaded so that, on receiving a __FlashStringHelper* argument, they correctly dereference the characters in the flash memory.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user4815162342
  • 141,790
  • 18
  • 296
  • 355
  • Thank you. This makes so much more sense to me now. Thank you. – iter May 18 '13 at 01:02
  • 1
    Here is another helpful answer: http://forum.arduino.cc/index.php?topic=91314.msg685761#msg685761 – Ben Sep 25 '15 at 17:17
  • I'm still uC/c/cpp noobie, so I need to ask now… OK, cool, so we store the STRINGS in flash memory [code memory] instead of the "data" memory – WHY? Does it make the code faster? Should I always use it? When should I avoid it? – MacDada Jul 03 '22 at 11:51
  • @MacDada I would expect that flash memory is preferred because data memory is read-write, so it's wasteful to spend it on constant strings that will never be changed. – user4815162342 Jul 03 '22 at 12:49
  • 1
    After a few months ^^ I think I can answer myself: flash memory is just BIGGER. Bigger than RAM. So, saving RAM is the reason to store the strings in the Flash. The cost is code clarity (manually marking every string literal with `F()` and `PSTR()`). – MacDada Jan 31 '23 at 17:22
6

BTW. For the ESP32 library, both of these functions are defined in the following files:

# PSTR :  ../Arduino/hardware/espressif/esp32/cores/esp32/pgmspace.h
# F    :  ../Arduino/hardware/espressif/esp32/cores/esp32/WString.h

And the F(x):

// An abstract class used as a means to provide a unique pointer type
// but really has no body
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
...

Also for ESP32, PSTR(x) is not needed and is just x: #define PSTR(s) (s).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
not2qubit
  • 14,531
  • 8
  • 95
  • 135