The avr-gcc compiler offers the F() macro as a good way to define strings in my statements and then place the strings in program memory. The strings end up being of type __FlashStringHelper, however, and I will get an error if I try to pass them to functions that expect "const char *".
I can cast each one and the code will function. For example this code will work:
int16_t LT_printf(const char *format, ...);
LT_printf((const char *)F("TESTING!\r\n"));
I can also define an overload function that does nothing but receive the __FlashStringHelper and then turn it into a (const char *). This also works:
int16_t LT_printf(const __FlashStringHelper *format, ...);
LT_printf(F("TESTING!\r\n"));
The second solution executes less efficiently than the first, but at least I don't have hundreds of casts in my code any more.
Is there a way to eliminate the casts inside every function call, but still not need the overload function?
Edited to Add More Examples that build (not that any of the examples are something I'd really do...I'm just interested in the pointer to const __FlashStringHelper):
typedef struct
{
char test_string[20];
} TEST_STRUCT_TYPE;
const TEST_STRUCT_TYPE PROGMEM test_struct = {"STRUCT TESTING!\r\n"};
const uint8_t PROGMEM test_array[] = {'A', 'R', 'R', 'A', 'Y', ' ', 'T', 'E', 'S', 'T', 'I', 'N', 'G', '!', '\r', '\n', NULL};
const char PROGMEM test_string[] = {"TEST TESTING!\r\n"};
void test()
{
LT_printf(test_string); // doesn't need a cast
LT_printf((const char *)F("F TESTING!\r\n")); // these need a cast
LT_printf((const char *)&test_struct);
LT_printf((const char *)test_array);
LT_printf((PGM_P)F("F TESTING!\r\n")); // this is the cleaner cast
LT_printf((PGM_P)&test_struct);
LT_printf((PGM_P)test_array);
}
This results in this output:
TEST TESTING!
F TESTING!
STRUCT TESTING!
ARRAY TESTING!
F TESTING!
STRUCT TESTING!
ARRAY TESTING!