I found this code sample from the FSBrowser (Flash File System) example in the ESP8266WebServer library:
replyServerError(FPSTR(FS_INIT_ERROR));
replyBadRequest(F("DIR ARG MISSING"));
I was a bit confused at what F()
and FPSTR()
do, so I looked up the source (WString.h
) and found this:
#define FPSTR(pstr_pointer) (reinterpret_cast<const __FlashStringHelper *>(pstr_pointer))
#define F(string_literal) (FPSTR(PSTR(string_literal)))
Which raised more questions. How does this code work and what does this added complexity gain over just using char*
or String
as is?
EDIT: Added Metrics
Here's the memory usage before and after I removed all 25 instances of F() from a file system class, measured by PlatformIO Project Inspector:
With F() | Without F() | Difference | |
---|---|---|---|
RAM Used | 29,488 bytes (36.0%) | 29,792 bytes (36.4%) | +304 bytes |
Flash Used | 355,312 bytes (34%) | 355,188 bytes (34.0%) | -124 bytes |
Total (uncompressed) | 359,472 bytes | 359,344 bytes | -128 bytes |
Adding F() decreases RAM usage by 1% and increases Flash by around half that. That's for a single class with 25 instances of F(). For a program containing 20x this code, the difference can be significant. However, you'll run out of RAM before you get there. The space savings will be limited to around 5-8%. Still not nothing.
F()
orFPSTR()
in my own code if I only plan on using the ESP8266?