user136: I'm currently changing some libraries to use flash instead of RAM for string storage so that I do not run out of SRAM on a project.
Some strings in the library are declared in this manner:
const char *testStringA = "ABC";

This is different to how I normally see this done:
const char testStringB[] = "DEF";

However, I think that these two are equivalent when declared const and initialised in the declaration. Both work fine in code.
I attempted to move these to flash:
const prog_char *testStringC PROGMEM = "GHI";

I then found that this didn't work. It was producing gobbledegook when printed.
However, following the more usual pattern of:
const prog_char testStringD[] PROGMEM = "JKL";

works fine.
I can see in the disassembly:
00000068 <testStringC>:
  68:   04 01                                               ..

0000006a <_ZL11testStringD>:
  6a:   4a 4b 4c 00                                         JKL.

So it is clear the pointer and PROGMEM results in the string/array not being initialised.
Why is this?
Example code:
#include <avr/pgmspace.h>

const int BUFFER_LEN = 20;

const char *testStringA = "ABC";
const char testStringB[] = "DEF";
const prog_char *testStringC PROGMEM = "GHI";
const prog_char testStringD[] PROGMEM = "JKL";

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

void loop()
{
    char buffer[BUFFER_LEN];

    Serial.println(testStringA);
    Serial.println(testStringB);

    strncpy_P(buffer, testStringC, BUFFER_LEN);
    Serial.println(buffer);

    strncpy_P(buffer, testStringD, BUFFER_LEN);
    Serial.println(buffer);

    delay(1000);

}


user368: What this line:
const prog_char *testStringC PROGMEM = "GHI";

does is to write prologue code to copy the characters in the string to SRAM, and then initializes the pointer stored in flash to this SRAM location. You must load the pointer via normal means, and then dereference the pointer as usual.
const char *str = pgm_read_word(&testStringC);
Serial.println(str);

This line:
const prog_char testStringD[] PROGMEM = "JKL";

creates the array of characters in flash, allowing you to access it as expected.

user379: Well, this question has been wisely answered in an answer to Stack Overflow question C: differences between char pointer and array.
Basically, what you're declaring as PROGMEM with,
const prog_char testStringD[] PROGMEM = "JKL";

is both the array and the memory it points to, that is, the elements of the array, both in current's scope stack. Whereas with:
const prog_char* testStringC PROGMEM = "GHI";

you declare a PROGMEM pointer to a constant string that may stay elsewhere in memory, but not declared as a PROGMEM string.
Though I did not test that, but you should try to declare:
const prog_char* testStringC PROGMEM = F("GHI");

to actually allocate the pointed string within the PROGMEM space. I guess it should be working, using Arduino's F() macro, which adds a lot of boilerplate code to actually have the same result as the array declaration.
As said in comments, if not in a global context, the PSTR() macro could be used instead of the F() macro.
Simpler is better: use the array declaration, not the pointer one!
Cf that other answer, the __flash qualifier is a third solution ;-)

136: <p>I'm currently changing some libraries to use flash instead of RAM for string storage so that I do not run out of SRAM on a project.</p>

<p>Some strings in the library are declared in this manner:</p>

<pre><code>const char *testStringA = "ABC";
</code></pre>

<p>This is different to how I normally see this done:</p>

<pre><code>const char testStringB[] = "DEF";
</code></pre>

<p>However, I think that these two are equivalent when declared const and initialised in the declaration. Both work fine in code.</p>

<p>I attempted to move these to flash:</p>

<pre><code>const prog_char *testStringC PROGMEM = "GHI";
</code></pre>

<p>I then found that this didn't work. It was producing gobbledegook when printed.</p>

<p>However, following the more usual pattern of:</p>

<pre><code>const prog_char testStringD[] PROGMEM = "JKL";
</code></pre>

<p>works fine.</p>

<p>I can see in the disassembly:</p>

<pre><code>00000068 &lt;testStringC&gt;:
  68:   04 01                                               ..

0000006a &lt;_ZL11testStringD&gt;:
  6a:   4a 4b 4c 00                                         JKL.
</code></pre>

<p>So it is clear the pointer and PROGMEM results in the string/array not being initialised.</p>

<p>Why is this?</p>

<p>Example code:</p>

<pre><code>#include &lt;avr/pgmspace.h&gt;

const int BUFFER_LEN = 20;

const char *testStringA = "ABC";
const char testStringB[] = "DEF";
const prog_char *testStringC PROGMEM = "GHI";
const prog_char testStringD[] PROGMEM = "JKL";

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

void loop()
{
    char buffer[BUFFER_LEN];

    Serial.println(testStringA);
    Serial.println(testStringB);

    strncpy_P(buffer, testStringC, BUFFER_LEN);
    Serial.println(buffer);

    strncpy_P(buffer, testStringD, BUFFER_LEN);
    Serial.println(buffer);

    delay(1000);

}
</code></pre>
 368: <p>What this line:</p>

<pre><code>const prog_char *testStringC PROGMEM = "GHI";
</code></pre>

<p>does is to write prologue code to copy the characters in the string to SRAM, and then initializes the <em>pointer</em> stored in flash to this SRAM location. You must load the pointer via normal means, and then dereference the pointer as usual.</p>

<pre><code>const char *str = pgm_read_word(&amp;testStringC);
Serial.println(str);
</code></pre>

<p>This line:</p>

<pre><code>const prog_char testStringD[] PROGMEM = "JKL";
</code></pre>

<p>creates the <em>array of characters</em> in flash, allowing you to access it as expected.</p>
 379: <p>Well, this question has been wisely answered in <a href="https://stackoverflow.com/a/1335836/1290438">an answer to Stack&nbsp;Overflow question <em>C: differences between char pointer and array</em></a>.</p>

<p>Basically, what you're declaring as PROGMEM with,</p>

<pre><code>const prog_char testStringD[] PROGMEM = "JKL";
</code></pre>

<p>is both the array and the memory it points to, that is, the elements of the array, both in current's scope stack. Whereas with:</p>

<pre><code>const prog_char* testStringC PROGMEM = "GHI";
</code></pre>

<p>you declare a PROGMEM pointer to a constant string that may stay elsewhere in memory, but not declared as a PROGMEM string.</p>

<p>Though I did <em>not</em> test that, but you should try to declare:</p>

<pre><code>const prog_char* testStringC PROGMEM = F("GHI");
</code></pre>

<p>to actually allocate the pointed string within the PROGMEM space. I <em>guess</em> it should be working, using Arduino's <a href="http://andybrown.me.uk/wk/wp-content/images//avr-gcc-4.7.0/WString.h" rel="nofollow noreferrer"><code>F()</code> macro</a>, which adds a lot of boilerplate code to actually have the same result as the array declaration.</p>

<p>As said in comments, if not in a global context, the <code>PSTR()</code> macro could be used instead of the <code>F()</code> macro.</p>

<p>Simpler is better: use the array declaration, not the pointer one!</p>

<p>Cf <a href="https://arduino.stackexchange.com/a/614/379">that other answer</a>, the <code>__flash</code> qualifier is a third solution ;-)</p>
