F() question - Syntax

I'm trying to use the F() FlashStringHelper macro to save some ram. I can get it to work with a single string, but can't figure out the syntax to use it for more than one.

Serial.println (F("I am here")); compiles & works!
Serial.println (F("MyVar =") + String(myVar) + F(" and YourVar =") + String(yourVar)); gives a bunch of errors including:
error: conversion from 'const __FlashStringHelper*' to 'const StringSumHelper' is ambiguous
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/WString.h:201: note: candidates are: StringSumHelper::StringSumHelper(long unsigned int)

So what would be the correct syntax to make my second example compile/work?

Yeah, I could do:
Serial.print (F("MyVar = "));
Serial.print (myVar);
Serial.print (F(" and YourVar = "));
Serial.println (yourVar);
but I was hoping not to turn 1 line into 4!

Separate Serial.print and line for each.

The most important advice is to stick to one type of strings.

F("MyVar =") is PROGMEM based char array's

String(myVar) is String class which is an often discussed wrapper around char array's.
It is not preferred as it is not memory efficient.

So instead of

Serial.print (F("MyVar =") + String(myVar) + F(" and YourVar =") + String(yourVar));

I advise to use:

Serial.print ( F("MyVar =") );
Serial.print ( myVar );
Serial.print ( F(" and YourVar =") );
Serial.print ( yourVar );

the print can handle all datatypes String() can.

Serial.print() & Serial.println() have methods for StringSumHelper so there is not any need to use F(). You just need to typecast the string:

Serial.println((String)"some text"+stringVar+intVar+byteVar+charArray);

If you have a method which will use this same syntax, then you will need the appropriate method definition:

motor::error(const StringSumHelper &msg) {
stopmotor();
Serial.println( msg );
}

Serial.print() & Serial.println() have methods for StringSumHelper so there is not any need to use F(). You just need to typecast the string:

Serial.println((String)"some text"+stringVar+intVar+byteVar+charArray);

What a load of shit. NO ONE should be encouraging the use of the resource-wasting String class. There is NOTHING to be gained from using one print() call vs. using more than one. NOTHING.

PaulS, not strictly true. For example, const String& type of a function parameter can serve as proxy for a few different argument types, including const _FlashStringHelper type that saves precious memory by storing strings in PROGMEM. And it is done transparently without introducing any unnecessary boilerplate code.

Regarding the OP's question, it can be easily done by wrapping F() calls into String() instead of char[] themselves, like so:

Serial.print(String(F("myIntVar =")) + String(myIntVar) + String(F(" and myStrVar =")) + myStrVar);

In addition, you could easily overload << operator as described here to concatenate these directly without having to wrap them into String, while also making your code more succinct:

Serial << F("myIntVar =") << myIntVar << F(" and myStrVar =") << myStrVar << '\n';

Regarding the OP's question, it can be easily done by wrapping F() calls into String() instead of char[] themselves, like so:

Try that (crap). Note the code and sram size.

Then, do it right:

Serial.print(F("myIntVar =");
Serial.print(myIntVar);
Serial.print(F(" and myStrVar =");
Serial.println(myStrVar);

Given the limited memory of the Arduino, why waste any resources when you don't need to?

If I want to write a function that supports the F macro, what would the parameters be? Thanks

PaulS, I already looked at memory consumption, and it doesn't add anything at all. String(const __FlashStringHelper*) constructor doesn't actually convert them into SRAM String, just stores the pointer. So it is exactly the same as if you did a single String.print() call. The << operator also doesn't consume any resources as it is translated to those Print calls by compiler. Please try

  int i = 1;
  String s = " test ";

with

  Serial.print(F("String.print()"));
  Serial.print(s);
  Serial.print(i);
  Serial.print('\n');

or

  Serial << F("String.print()") << s << i << '\n';

Memory consumption stays exactly the same at 206 bytes in my code (I have other pieces there as well, so you may get a different value). Moreover, if I use

Serial.println(i);

as the last call in the first scenario, memory consumption jumps to 222 bytes (!), even though println() is supposed to add only one extra '\r' character at the end.

shawnlg, you just write yourFunc(const String& str). Anything that accepts String will automatically accept F() calls.

shawnlg:
If I want to write a function that supports the F macro, what would the parameters be? Thanks

void MyFmacroFunction( const __FlashStringHelper * fsh );

An example of how to use it...

https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/Print.cpp#L43-L56

denvlad:
PaulS, I already looked at memory consumption, and it doesn't add anything at all.

Look again.

Flash: 3,350 vs 1,880.
SRAM: 210 vs 200.

...for a simple example. Plus heap space to store the string.

String will automatically accept F() calls.

Yup. And String is just as expensive as ever. Using the F-macro does not change that fact.

denvlad:
String(const __FlashStringHelper*) constructor doesn't actually convert them into SRAM String, just stores the pointer.

Really?

String::String(const __FlashStringHelper *pstr)
{
        init();
        *this = pstr;
}

"just stores the pointer" you say?

Let's take a closer look at this assignment operator that the String class has redefined for our convenience.

String & String::operator = (const __FlashStringHelper *pstr)
{
        if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
        else invalidate();

        return *this;
}
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
{
        if (!reserve(length)) {
                invalidate();
                return *this;
        }
        len = length;
        strcpy_P(buffer, (PGM_P)pstr);
        return *this;
}

So, does it make a copy to SRAM or not?

Could you post an example? It's

Flash: 5,436 vs 5,450
SRAM: 206 vs 206

in my example from above (only a minor increase in flash use for my suggested solution, but that is a cheap price to pay given that there's much more flash than RAM).

Also, I don't see how that is different from individual calls to String.print(), given that the overloaded operator is translated to essentially the same code. Perhaps you're talking about something else? Like __FlashStringHelper* vs String& ? In addition, I don't think it uses copy (which would lead to extra heap) - please take a look at size_t Print::print(const __FlashStringHelper *ifsh) in Print.cpp, it directly reads bytes from PROGMEM and streams them to the output from what I understand.

oqibidipo:

String & String::operator = (const __FlashStringHelper *pstr)

{
        if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
        else invalidate();

return *this;
}




So, does it make a copy to SRAM or not?

Ok, looks like I was wrong in this case, though I was leaning more toward the second solution involving <<. My values comparing the two are for that case only. Though could the current implementation involving String translation be improved by not having to copy the data but rather read it directly when String content is requested? I thought that was the whole point of storing things in PROGMEM..[/code]

denvlad:
Could you post an example?

Next post.

...given that the overloaded operator is translated to essentially the same code.

It is not. Did you see oqibidipo's post?

I don't think it uses copy (which would lead to extra heap)

It does. Did you see oqibidipo's post?

please take a look at size_t Print::print(const __FlashStringHelper *ifsh)

That method is irrelevant. When an F-macro string is wrapped with a String that method is not used.

void yourFunc( const String& str )
{
  Serial.println( str );
}

// Adjust the comments
/**/
void yourFunc( const __FlashStringHelper * fsh )
{
  Serial.println( fsh );
}
/**/

void setup() 
{
  Serial.begin( 115200 );
}

void loop() 
{
  yourFunc( F( "yourFunc test." ) );
}

Coding Badly, sorry for miscommunication - I was referring to '<<' solution all the way when I was talking about them being identical. oqibidipo' examples make it obvious that the strings are copied. Otherwise yes, either direct .print of one variable at a time (or its << shorthand one-liner) make it most efficient and RAM-saving wise. I would argue though that it all depends on exact use case and whether code readability/compactness is worth a trade-off with saving RAM.

I missed reply #14. Sorry about that. Probably a side effect of purging @zoomkat's off-topic trolling.

So...

denvlad:
For example, const String& type of a function parameter can serve as proxy for a few different argument types, including const _FlashStringHelper...

Not correct?

Yes, now I see that's not correct. Again, no need to wrap in String() though if you could use a '<<' shorthand in this particular use case. Of course, one will need to overload their functions with a separate case for (const __FlashStringHelper*) if they want to use both SRAM and PROGMEM 'strings' with a custom function.

Yep, thanks for the explanation btw. Hopefully our posts will help others who learn this stuff in the future.