Static array of strings

What I am trying to do is define an array of strings but with a minimum memory footprint.

What I need is a list of color names which matches a color RGB value. I know I can get it to work by defining two arrays, one with color names and one matching one with color values like:

String colorNames[] = {"black","red","green"};
String colorValues[] = {"000000000","255000000","000255000"};

Than if someone asks for a color (on a webpage) I can look it up in the colorNames array and take the matching index of colorValues. But if I have more colors (which I plan to do) I am afraid it will eat into my memory to much.

What I am looking for is a suggestion on how to get this working.

Use char arrays in flash. There is lots of info about PROGMEM on this forum, and the learning section. Then almost all of the RAM is freed.

In RAM a String has a small overhead for each string (length, buffer length, pointer to data). Strings can be handy, but are not a great choice when you are trying to keep a "minimum memory footprint".

A String is useful for text that needs to change, definitely not static stuff.

Hint: Color values like "255000000" should be stored as an integer (3/4 bytes vs 10 chars).

What I am trying to do is define an array of strings but with a minimum memory footprint.

Well, using Strings in NOT the answer.

But if I have more colors (which I plan to do) I am afraid it will eat into my memory to much.

Will the list of colors change while the Arduino is running?

The array of colors will not change during runtime.

And indeed, 3 bytes makes more sense than a string of 9.

The array of colors will not change during runtime.

So, PROGMEM is the place for the strings and values.

Thanks for the tips so far. I am trying to code using PROGMEM and after some unsuccessful attempts I tried just copying the sample code:

/*
 PROGMEM string demo
 How to store a table of strings in program memory (flash),
 and retrieve them.

 Information summarized from:
 http://www.nongnu.org/avr-libc/user-manual/pgmspace.html

 Setting up a table (array) of strings in program memory is slightly complicated, but
 here is a good template to follow.

 Setting up the strings is a two-step process. First define the strings.
*/

#include <pgmspace.h>
const char string_0[] PROGMEM = "String 0";   // "String 0" etc are strings to store - change to suit.
const char string_1[] PROGMEM = "String 1";
const char string_2[] PROGMEM = "String 2";
const char string_3[] PROGMEM = "String 3";
const char string_4[] PROGMEM = "String 4";
const char string_5[] PROGMEM = "String 5";


// Then set up a table to refer to your strings.

const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5};

char buffer[30];    // make sure this is large enough for the largest string it must hold

void setup()
{
  Serial.begin(9600);
  while(!Serial);
  Serial.println("OK");
}


void loop()
{
  /* Using the string table in program memory requires the use of special functions to retrieve the data.
     The strcpy_P function copies a string from program space to a string in RAM ("buffer").
     Make sure your receiving string in RAM  is large enough to hold whatever
     you are retrieving from program space. */


  for (int i = 0; i < 6; i++)
  {
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // Necessary casts and dereferencing, just copy.
    Serial.println(buffer);
    delay( 500 );
  }
}

Unfortunately all it does is give me an exception (28) and a reboot. I did not mention I am programming this on an ESP8266 because I hoped/thought it did not matter. Looks like it does.

The ESP core does have PROGMEM like functionality added to it. People are using my PGMWrap library fine on an ESP.

I think your issue is related to pointer sizes on an ESP.

You are using pgm_read_word() for a two byte pointer (which is correct in AVR), but an ESP has a 32 bit/4byte pointer. Your pointer accesses may need to use pgm_read_dword(), but its would be even safer to use pgm_read_ptr()

Not related to storage, but if you have two corresponding arrays then it can make sense to store them as structs.

I'm not 100% sure about how to get everything in progmem, but without that factor, it's like:

struct ColorPair {
  char *name;
  int colour;
};

ColorPair colour[] = {
  {"Red", 0xFF0000},
  {"Black", 0x000000},
  {"Pink", 0xFF8888},
  // etc
};

I think the F() macro has a type on it (far_helper or something), so you'd declare "name" to be one of those and put an F() around the strings.

PaulMurrayCbr: Not related to storage, but if you have two corresponding arrays then it can make sense to store them as structs.

I'm not 100% sure about how to get everything in progmem, but without that factor, it's like:

char *name will need to be an array otherwise the string will still reside in RAM, only its pointer is copied to flash. This is similar to storing a String in PROGMEM, the actual string data is located elsewhere.

For common length text this is perfect, however if one option is 100 chars, and the rest 3 or 4 then there can be a bit of waste (bit flash has always been less precious to me anyway).

Another option which was popular in Windows programming years ago was multistrings. A single PROGMEM array could hold all strings (each typically separated by null and the array terminated with a double null). Then the struct pointers can simply reference the start of the string.

As far as I know (AVR anyway) F() does not work on global declarations, it needs to be used within a function.