Interesting... Looks like the 'wchar' warning only happens for snprintf()
, not snprintf_P()
.
Also, the warnings do not prevent the compiler from generating the right code. When the pointer's address space matches the format string, the string is displayed correctly. When the pointer's address space does not match the format string, the string is not displayed correctly.
char buf[256];
void setup()
{
Serial.begin(115200);
delay(200);
Serial.println("Valid pointers:");
snprintf(buf, 255, "snprintf-s: %s", "NORMAL-STRING");
Serial.println(buf);
snprintf(buf, 255, "snprintf-S: %S", PSTR("PSTR-STRING"));
Serial.println(buf);
snprintf(buf, 255, "snprintf-S: %S", (const char *) F("F_MACRO-STRING"));
Serial.println(buf);
snprintf_P(buf, 255, PSTR("snprintf_P-s: %s"), "NORMAL-STRING");
Serial.println(buf);
snprintf_P(buf, 255, PSTR("snprintf_P-S: %S"), PSTR("PSTR-STRING"));
Serial.println(buf);
snprintf_P(buf, 255, (const char *) F("snprintf_P-S: %S"), (const char *) F("F_MACRO-STRING"));
Serial.println(buf);
Serial.println("Invalid pointers:");
snprintf(buf, 255, "snprintf-s: %s", PSTR("PSTR-STRING"));
Serial.println(buf);
snprintf(buf, 255, "snprintf-s: %s", (const char *) F("F_MACRO-STRING"));
Serial.println(buf);
snprintf(buf, 255, "snprintf-S: %S", "NORMAL-STRING");
Serial.println(buf);
snprintf_P(buf, 255, PSTR("snprintf_P-s: %s"), PSTR("PSTR-STRING"));
Serial.println(buf);
snprintf_P(buf, 255, PSTR("snprintf_P-s: %s"), (const char *) F("F_MACRO-STRING"));
Serial.println(buf);
snprintf_P(buf, 255, PSTR("snprintf_P-S: %S"), "NORMAL-STRING");
Serial.println(buf);
}
void loop() {}
Run on an Arduino UNO:
Valid pointers:
snprintf-s: NORMAL-STRING
snprintf-S: PSTR-STRING
snprintf-S: F_MACRO-STRING
snprintf_P-s: NORMAL-STRING
snprintf_P-S: PSTR-STRING
snprintf_P-S: F_MACRO-STRING
Invalid pointers:
snprintf-s:
snprintf-s: ⸮⸮⸮
snprintf-S: F_MACRO-STRING
snprintf_P-s:
snprintf_P-s:
snprintf_P-S: F_MACRO-STRING
NOTE: The two appearances of "F_MACRO-STRING" under "Invalid pointers:" were RAM pointers to "NORMAL-STRING". Looks like the address of "NORMAL-STRING" in RAM just happened to match the address of "F_MACRO-STRING" in PROGMEM.
The compiler warnings are:
/Users/john/Documents/Arduino/sketch_aug11a/sketch_aug11a.ino: In function 'void setup()':
/Users/john/Documents/Arduino/sketch_aug11a/sketch_aug11a.ino:13:59: warning: format '%S' expects argument of type 'wchar_t*', but argument 4 has type 'const char*' [-Wformat=]
snprintf(buf, 255, "snprintf-S: %S", PSTR("PSTR-STRING"));
^
/Users/john/Documents/Arduino/sketch_aug11a/sketch_aug11a.ino:16:74: warning: format '%S' expects argument of type 'wchar_t*', but argument 4 has type 'const char*' [-Wformat=]
snprintf(buf, 255, "snprintf-S: %S", (const char *) F("F_MACRO-STRING"));
^
/Users/john/Documents/Arduino/sketch_aug11a/sketch_aug11a.ino:37:55: warning: format '%S' expects argument of type 'wchar_t*', but argument 4 has type 'const char*' [-Wformat=]
snprintf(buf, 255, "snprintf-S: %S", "NORMAL-STRING");
^
Sketch uses 3980 bytes (12%) of program storage space. Maximum is 32256 bytes.
Global variables use 522 bytes (25%) of dynamic memory, leaving 1526 bytes for local variables. Maximum is 2048 bytes.
Perhaps the "-Wformat" argument to the compiler could be used to suppress the spurious warnings.