Playing with PROGMEM and __FlashStringHelper

Hi all. The code below compiles and runs correctly on an Adafruit ESP8266 Huzzah. I'm just wondering if there's a syntax that will assign the 'hello' variable directly from the string literal without going through the intermediate variable 'string'. Thanks.

void setup() {
  static char string[] PROGMEM  =  "Hello World";
  __FlashStringHelper *hello = (__FlashStringHelper *)string;
  Serial.begin(115200);
  delay(2000);

  Serial.println();
  Serial.println(hello);
}

void loop() {}

strcpy_P ? (I'm not really clear why you want)

AWOL: strcpy_P ?

Don't think so. I want to accomplish this, but in a single line:

  static char string[] PROGMEM  =  "Hello World";
  __FlashStringHelper *hello = (__FlashStringHelper *)string;

Is there such a syntax?

gfvalvo: Don't think so. I want to accomplish this, but in a single line:

  static char string[] PROGMEM  =  "Hello World";
  __FlashStringHelper *hello = (__FlashStringHelper *)string;

Is there such a syntax?

I'm not sure I understand either...

you are creating a new pointer to string called hello..?..?

I was thinking of a string in PROGMEM that I could print from multiple places in my code without having to have 'F("This is my string")' everywhere. That way, if I want to change it (at compile time obviously), I only need to do so in one place. This does the job:

void setup() {
  const __FlashStringHelper *hello = F("Hello World");
  Serial.begin(115200);
  delay(2000);

  Serial.println();
  Serial.println(hello);
  Serial.println(hello);
}

void loop() {
}

So does this, but it takes up more PROGMEM space:

void setup() {
  #define hello F("Hello World")
  Serial.begin(115200);
  delay(2000);

  Serial.println();
  Serial.println(hello);
  Serial.println(hello);
}

void loop() {
}
const char PROGMEM hello[] = "Hello World";
    :
  Serial.print((__FlashStringHelper *)hello);

PROGMEM adequately puts strings in flash. __FlashStringHelper is only needed to fool C++ into calling the proper version of print() The F() macro contains additional magic to put the literal string into PROGMEM that isn't needed if you've put it there yourself; it might be worthwhile creating a new macro (FV for "Flash Variable"?) to make things prettier:

   #define FV(s) ((__FlashStringHelper*)(s))
   const char PROGMEM hello[] = "Hello World";
    :
  Serial.print(FV(hello));

(all this assuming that the ESP8266 has things set up to behave the way that they do on AVR...)

westfw: (all this assuming that the ESP8266 has things set up to behave the way that they do on AVR...)

I had wondered about that. Adding the PROGMEM stuff does change the memory usage report from the IDE, so it does do SOMETHING.

Think I prefer:

const __FlashStringHelper *hello = F("Hello World");

It's succinct and doesn't require any extra baggage inside the print() statement.

const __FlashStringHelper *hello = F("Hello World");

It’s succinct and doesn’t require any extra baggage inside the print() statement.

It doesn’t seem to work in global context, though:

             /Applications/arduino/Arduino-1.8.5.app/Contents/Java/hardware/arduino/avr/cores/arduino/WString.h:38:74: error: statement-expressions are not allowed outside functions nor in template-argument lists
              #define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
const __FlashStringHelper *hello2= F("Hello World");

@gfvalvo, is there a reason you are not just using the Flash Library?

As I said in Reply #4, I was looking for a way to define a PROGMEM string once and then be able to print it from multiple locations in the code. So, since it's defined in only one place, I could change it (at compile time) to a different string and the change would be effective everywhere it's used. This works (even in Global space):

const char string[] PROGMEM  =  "Hello World";
  __FlashStringHelper *hello = (__FlashStringHelper *)string;

If you are responding to my post you did not answer the question.

I think the @westfw option seems more explicable in the natural code:

#define FV(x) (__FlashStringHelper*)(x)

template<class T> inline Print &operator << (Print &obj, T arg)
{
  obj.print(arg);
  return obj;
};

const char hello[] PROGMEM  =  "Hello";
const char world[] PROGMEM  =  "World";

void setup() 
{
  Serial.begin(9600);
  Serial << FV(hello) << F(" ") << FV(world);
}

void loop() {
  // put your main code here, to run repeatedly:

}

what you are doing (it seems to me) obfuscates that the string is, well, special

[quote author=Coding Badly date=1512953363 link=msg=3519464] If you are responding to my post you did not answer the question. [/quote] Guess I don't know. Please provide an example of accomplishing this using the Flash Library:

gfvalvo: As I said in Reply #4, I was looking for a way to define a PROGMEM string once and then be able to print it from multiple locations in the code. So, since it's defined in only one place, I could change it (at compile time) to a different string and the change would be effective everywhere it's used.

Searching using the obvious keywords…
https://www.google.com/search?q=arduino+flash+library

…leads to this…
http://arduiniana.org/libraries/flash/

…which has a link to download the library.

The library is not compatible with the latest Arduino IDE. Add the following to line 30 in Flash.h…

typedef char prog_char;

Let’s work with this example…

#include <Flash.h>

FLASH_STRING(string, "Hello World");

void setup(void)
{
  Serial.begin( 250000 );
  
/* Does not work with the current Flash Library...
  Serial.print( string ); */

  // Does work...
  Serial << string;

  // Does work...
  string.print( Serial );
}

void loop(void) { }

The usual way to print Flash strings does not work with the current versions of the Arduino IDE and the Flash Library. It worked in the past which means a simple change is likely to get it working again. (Adding an operator __FlashStringHelper*() const is likely all that is needed.)

The only annoyance is the unusual syntax for defining a string.

[quote author=Coding Badly date=1512956024 link=msg=3519485] The only annoyance is the unusual syntax for defining a string. [/quote] Not seeing a whole lot of value added over the code in Reply #9, which is actually the code in my original post.