This is again a suggestion for a minor
In small embedded programs, often strings of a fixed length are to be output, for example on a LCD display. Thus, some of the functions to accomplish this take as argument a string, but they ignore the trailing zero anyway.
To spare FLASH, the following definition/initialisation can be used for a string to be placed to FLASH:
char s[strlen("ABCD")] = "ABCD";
This occupies exactly 4 bytes in FLASH.
As an analogy to PSTR macro and memcpy_P() function, using this feature, I propose the following macros to be added to
# define PSNZ(s) (__extension__({static char __c[__builtin_strlen(s)] PROGMEM = (s); &__c[0];})) # define PSNZcpy(m, s) memcpy_P((uint8_t *)(m), PSNZ(s), __builtin_strlen(s))
So, now, if one has a function printing 4 bytes from FLASH, it is as easy to use as Print4BytesFromFlashToLCD(PSNZ("ABCD"));
These can of course be defined also for the "far" memory versions along the outlines sketched here:
# define PFSNZ(s) (__extension__({static char __c[__builtin_strlen(s)] PROGMEM_FAR = (s); GET_FAR_ADDRESS(__c[0]);})) # define PS1SNZ(s) (__extension__({static char __c[__builtin_strlen(s)] PROGMEM_SEG1 = (s); PROGMEM_SEG1_BASE + (uint16_t)&__c[0];})) # define PS2SNZ(s) (__extension__({static char __c[__builtin_strlen(s)] PROGMEM_SEG2 = (s); PROGMEM_SEG2_BASE + (uint16_t)&__c[0];})) # define PS3SNZ(s) (__extension__({static char __c[__builtin_strlen(s)] PROGMEM_SEG3 = (s); PROGMEM_SEG3_BASE + (uint16_t)&__c[0];})) # define PFSNZcpy(m, s) memcpy_PF((uint8_t *)(m), PFSNZ(s), __builtin_strlen(s)) # define PS1SNZcpy(m, s) memcpy_PF((uint8_t *)(m), PS1SNZ(s), __builtin_strlen(s)) # define PS2SNZcpy(m, s) memcpy_PF((uint8_t *)(m), PS2SNZ(s), __builtin_strlen(s)) # define PS3SNZcpy(m, s) memcpy_PF((uint8_t *)(m), PS3SNZ(s), __builtin_strlen(s))
Comments, please.
Jan Waclawek
PS. For those wondering whether this is legal - in C99 it is: I've been taught recently too...