# Help with PROGMEM and char arrays

**URL:** <https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675>\
**Category:** Programming\
**Created:** [February 8, 2026, 1:41am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675 "2026-02-08T01:41:14Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 1:41am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/1 "2026-02-08T01:41:14Z")

</div>

I currently have this Pro Mini code in a sketch:

```arduino
//global:

char *menuText[] = { // pointers to Menu options
  (char*)"SET DATE/TIME", // set RTC date and time
  (char*)"SET CHKIN HOURS", // set one to three daily checkin hours
  (char*)"AUTO ADJUST DST", // enable auto adjust for daylight saving
  (char*)"SET BUZZER TIME", // set alarm buzzer time if check-in missed
  (char*)"SET QUICK TRIES", // number of immediate tries to send PUSH
  (char*)"ONE-HOUR RETRIES", // number of retries on successive hours if PUSH still fails
  (char*)"SET WIFI & KEYS", // set WiFi and Pushover keys
  (char*)"TESTPUSH TO ME", // send test PUSH notification to my phone
  (char*)"TESTPUSH TO ALL", // send to group
  (char*)"TRIM RTC SPEED", // adjust RTC oscillation speed
  (char*)"COINCELL VOLTAGE", // check voltage of RTC backup coin cell
  (char*)"EXIT MENU"
};

// and then later:

lcd.print(menuText[menuIndex]);

```

I don't remember where I got that, but it works fine. But it puts all the strings in ram. I would like to keep them in flash, and print them from there. So far, I've concluded I need to make everything const, but I don't know how to set up the array as PROGMEM, or do the printing. Any suggestions would be appreciated.

---

<div class="post-metadata">

**Author:** ![xfpd](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/xfpd/32/1120236_2.png) [@xfpd](https://forum.arduino.cc/u/xfpd)\
**Post date:** [February 8, 2026, 2:00am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/2 "2026-02-08T02:00:25Z")

</div>

```arduino
const type array[] PROGMEM = {
  "one",
  "two",
  "tre"
};

```

I used "flat" arrays, so inside the braces, the commas go away, and it's just one long string, but my strings in one array were all the same length so I can calculate where I need to read.

> **[LEDsequencer - Wokwi ESP32, STM32, Arduino Simulator](https://wokwi.com/projects/425863953438420993)**
>
> Run IoT and embedded projects in your browser: ESP32, STM32, Arduino, Pi Pico, and more. No installation required!

Then, I read the stored data out in bytes using: `pgm_read_byte()`

```arduino
void sequencer(char list[], int columns, int loops) {
  for (int lop = 0; lop < loops; lop++) { // count through loops
    loopTime(columnSpacing, columns, loops); // display Loop Time
    for (int col = 0; col < columns; col++) { // count through row length
      for (int row = 0; row < ledCount; row++) { // count through number of LEDs
        switch (pgm_read_byte(&list[row * columns + col])) { // locate element row and column location
          case '*': digitalWrite(ledPin[row], HIGH); break; // turn LED ON
          case '.': digitalWrite(ledPin[row], LOW); break; // turn LED OFF
          default: break;
        }
      }
      delay(columnSpacing); // regulate the speed of the sequence
    }
  }
  firstTime = 1; // set first time flag for LoopTime display
}

```

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [February 8, 2026, 2:13am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/3 "2026-02-08T02:13:10Z")

</div>

There are a couple of ways to do it.

If all the char arrays are the same length, or nearly the same length, then a 2-dimensional array can be used:

```arduino
const char menuText[][17] PROGMEM = { // pointers to Menu options
  "SET DATE/TIME", // set RTC date and time
  "SET CHKIN HOURS", // set one to three daily checkin hours
  "AUTO ADJUST DST", // enable auto adjust for daylight saving
  "SET BUZZER TIME", // set alarm buzzer time if check-in missed
  "SET QUICK TRIES", // number of immediate tries to send PUSH
  "ONE-HOUR RETRIES", // number of retries on successive hours if PUSH still fails
  "SET WIFI & KEYS", // set WiFi and Pushover keys
  "TESTPUSH TO ME", // send test PUSH notification to my phone
  "TESTPUSH TO ALL", // send to group
  "TRIM RTC SPEED", // adjust RTC oscillation speed
  "COINCELL VOLTAGE", // check voltage of RTC backup coin cell
  "EXIT MENU"
};

lcd.print((__FlashStringHelper*)&menuText[menuIndex])

```

If the char arrays vary in length, it is more efficient to have an array of pointers to the char arrays:

```arduino

const char text00[] PROGMEM = "SET DATE/TIME"; // set RTC date and time
const char text01[] PROGMEM = "SET CHKIN HOURS"; // set one to three daily checkin hours
const char text02[] PROGMEM = "AUTO ADJUST DST"; // enable auto adjust for daylight saving
const char text03[] PROGMEM = "SET BUZZER TIME"; // set alarm buzzer time if check-in missed
const char text04[] PROGMEM = "SET QUICK TRIES"; // number of immediate tries to send PUSH
const char text05[] PROGMEM = "ONE-HOUR RETRIES"; // number of retries on successive hours if PUSH still fails
const char text06[] PROGMEM = "SET WIFI & KEYS"; // set WiFi and Pushover keys
const char text07[] PROGMEM = "TESTPUSH TO ME"; // send test PUSH notification to my phone
const char text08[] PROGMEM = "TESTPUSH TO ALL"; // send to group
const char text09[] PROGMEM = "TRIM RTC SPEED"; // adjust RTC oscillation speed
const char text10[] PROGMEM = "COINCELL VOLTAGE"; // check voltage of RTC backup coin cell
const char text11[] PROGMEM = "EXIT MENU";

const char* const menuText[] PROGMEM = { // pointers to Menu options
  text00,
  text01,
  text02,
  text03,
  text04,
  text05,
  text06,
  text07,
  text08,
  text09,
  text10,
  text11,
};

lcd.print((__FlashStringHelper*)pgm_read_ptr(&menuText[menuIndex]));
```

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 2:18am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/4 "2026-02-08T02:18:56Z")

</div>

Thanks very much. But each string has to have it's own PROGMEM? I couldn't just add PROGMEM to the array I had originally, with the (char\*) things?

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [February 8, 2026, 2:20am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/5 "2026-02-08T02:20:46Z")

</div>

No, unfortunately that does not work. The array of char\* would go into PROGMEM, but the char arrays would go into ram.

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 2:21am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/6 "2026-02-08T02:21:45Z")

</div>

Ok, I understand. Thanks again.

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [February 8, 2026, 2:24am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/7 "2026-02-08T02:24:06Z")

</div>

Note that this does rely on the lcd library inheriting from print, which has an overload of the print() function that uses \_\_FlashStringHelper\* to signify that a char\* points to PROGMEM instead of ram.

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 2:26am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/8 "2026-02-08T02:26:02Z")

</div>

I don't know what that means. But if it compiles, does that mean the library does all that correctly?

---

<div class="post-metadata">

**Author:** ![david\_2018](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/david_2018/32/1013044_2.png) [@david\_2018](https://forum.arduino.cc/u/david_2018)\
**Post date:** [February 8, 2026, 2:27am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/9 "2026-02-08T02:27:40Z")

</div>

Yes, if it compiles then the library has a function that takes the \_\_FlashStringHelper\*. All the lcd libraries I'm familiar with will work, but there is always the chance someone is using there own code or a more obscure library.

---

<div class="post-metadata">

**Author:** ![dilberto](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/dilberto/32/1126465_2.png) [@dilberto](https://forum.arduino.cc/u/dilberto)\
**Post date:** [February 8, 2026, 2:38am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/10 "2026-02-08T02:38:53Z")

</div>

The problems of a non-Von Neumann architecture ...

---

<div class="post-metadata">

**Author:** ![xfpd](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/xfpd/32/1120236_2.png) [@xfpd](https://forum.arduino.cc/u/xfpd)\
**Post date:** [February 8, 2026, 2:52am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/11 "2026-02-08T02:52:07Z")

</div>

> [@ShermanP](#):
>
> add PROGMEM to the array I had originally

Too many dimensions cause pointer/reference issues.

That is why I (in my link) removed all the commas after the quotes to make the data one-dimension. Only needed a little row/col math to get the right data.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [February 8, 2026, 8:36am UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/12 "2026-02-08T08:36:34Z")

</div>

Not as well that casting as char \* a string literal is not a good practice - that should be const char \* but it’s implicit .

As you usually are not short for flash, I find the option of using fixed size arrays (to the longest string thus)) the easy way forward to define and use the array.

You do have to cast the pointer to \_\_FlashStringHelper\* when using it though as the compiler won’t know.

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 3:14pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/13 "2026-02-08T15:14:43Z")

</div>

> [@dilberto](#):
>
> The problems of a non-Von Neumann architecture ...

Indeed. Before I got to Arduino, I did assembler on the MSP430. You could address anything, anywhere. But I guess at runtime Harvard is faster.

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 3:16pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/14 "2026-02-08T15:16:53Z")

</div>

> [@J-M-L](#):
>
> As you usually are not short for flash, I find the option of using fixed size arrays (to the longest string thus)) the easy way forward to define and use the array.

So then for strings that are shorter, they are just null-filled at the end? Printing would stop at the first null.

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [February 8, 2026, 3:17pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/15 "2026-02-08T15:17:35Z")

</div>

> [@ShermanP](#):
>
> for strings that are shorter, they are just null-filled at the end? Printing would stop at the first null.

Yes and Yes.

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [February 8, 2026, 3:17pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/16 "2026-02-08T15:17:57Z")

</div>

> [@J-M-L](#):
>
> As you usually are not short for flash, I find the option of using fixed size arrays (to the longest string thus)) the easy way forward to define and use the array.

Agreed. But if you really had your heart set on a jagged array in PROGMEM, the below technique works. It's kind of slick, but it does require the pointer array to be in RAM. So, it may not be worth the trouble.

```arduino
#define PROGMEM_STRING(stringLiteral) [](){static const char s[] PROGMEM = stringLiteral; return reinterpret_cast<const __FlashStringHelper*>(&s[0]);} ()

const __FlashStringHelper* menuText[] = {
  PROGMEM_STRING("SET DATE/TIME"),
  PROGMEM_STRING("SET CHKIN HOURS"),
  PROGMEM_STRING("AUTO ADJUST DST"),
  PROGMEM_STRING("SET BUZZER TIME"),
  PROGMEM_STRING("SET QUICK TRIES"),
  PROGMEM_STRING("ONE-HOUR RETRIES"),
  PROGMEM_STRING("SET WIFI & KEYS"),
  PROGMEM_STRING("TESTPUSH TO ME"),
  PROGMEM_STRING("TESTPUSH TO ALL"),
  PROGMEM_STRING("TRIM RTC SPEED"),
  PROGMEM_STRING("COINCELL VOLTAGE"),
  PROGMEM_STRING("EXIT MENU")
};

void setup() {
  Serial.begin(115200);
  delay(1000);
  for (auto ptr : menuText) {
    Serial.println(ptr);
  }
}

void loop() {
}
```

**Output:**

```arduino
SET DATE/TIME
SET CHKIN HOURS
AUTO ADJUST DST
SET BUZZER TIME
SET QUICK TRIES
ONE-HOUR RETRIES
SET WIFI & KEYS
TESTPUSH TO ME
TESTPUSH TO ALL
TRIM RTC SPEED
COINCELL VOLTAGE
EXIT MENU

```

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 3:22pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/17 "2026-02-08T15:22:42Z")

</div>

> [@gfvalvo](#):
>
> ```arduino
> #define PROGMEM_STRING(stringLiteral) [](){static const char s[] PROGMEM = stringLiteral; return reinterpret_cast<const __FlashStringHelper*>(&s[0]);} ()
> 
> ```

That just rolls off the tongue, doesn't it. 🙂

---

<div class="post-metadata">

**Author:** ![gfvalvo](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gfvalvo/32/1013044_2.png) [@gfvalvo](https://forum.arduino.cc/u/gfvalvo)\
**Post date:** [February 8, 2026, 3:25pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/18 "2026-02-08T15:25:08Z")

</div>

> [@ShermanP](#):
>
> That just rolls off the tongue, doesn't it.

That's why it's hidden in a macro.

---

<div class="post-metadata">

**Author:** ![ShermanP](https://avatars.discourse-cdn.com/v4/letter/s/b19c9b/32.png) [@ShermanP](https://forum.arduino.cc/u/ShermanP)\
**Post date:** [February 8, 2026, 3:39pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/19 "2026-02-08T15:39:47Z")

</div>

Yes, I guess the definition of F would look very similar.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [February 8, 2026, 4:06pm UTC](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675/20 "2026-02-08T16:06:45Z")

</div>

> [@ShermanP](#):
>
> So then for strings that are shorter, they are just null-filled at the end? Printing would stop at the first null

Excatly. Actually the String literal (the thing between the double quotes) does have a hidden null terminator and if that does not fill in all the bytes of the array then the compiler (it's a global variable) will pad that with 0.

[Next page](https://forum.arduino.cc/t/help-with-progmem-and-char-arrays/1429675.md?page=2)
