[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] PROGMEM on compound-literal arrays
From: |
Georg-Johann Lay |
Subject: |
Re: [avr-gcc-list] PROGMEM on compound-literal arrays |
Date: |
Sun, 30 Oct 2016 20:17:51 +0100 |
User-agent: |
Thunderbird 2.0.0.24 (Windows/20100228) |
Paul "LeoNerd" Evans schrieb:
((TLDR: PROGMEM on compound-literal arrays is silently ignored.
Please either implement or make it a noisy warning/error.))
If I define a function that takes a byte array, e.g.
void i2c_write(size_t len, const uint8_t *data);
I find it nice to be able to call that with compound-literal arrays
inline:
i2c_write(4, (const uint8_t[]){0x10, 0x20, 0x30, 0x40});
((The reason I'm using this inline notation rather than a static
declaration made elsewhere is that my data in fact comes from a
build-time translation step, and most of the arguments to the function
call are embedded with an #include directive to embed the data in the
source code.))
Well, code like
i2c_write (
#include "data.def"
);
where data.def contains
4, (const uint8_t[]){0x10, 0x20, 0x30, 0x40}
might be in order for auto generated code, but solutions that first
define a variable and then use it by its name is superior. One reason
is that multiple uses of the same ad hoc data don't generate different
instances.
If I want to store the data in PROGMEM instead and write a _P version,
then this syntax won't do:
i2c_write_P(4, (const PROGMEM uint8_t[]){0x10, 0x20, 0x30, 0x40});
While it does parse and compile successfully, the data doesn't end in
in PROGMEM, so the pgm_read_byte() function doesn't find it, and
returns junk. There's no compile-time warning or error that it hasn't
honoured it though, so debugging this failure can be hard.
The following syntax does work as an alternative:
i2c_write_P(4, ({
static const PROGMEM uint8_t data[] = {0x10, 0x20, 0x30, 0x40};
data;
}));
I.e. a statement-expression that embeds a static PROGMEM declaration
and yields it.
Would it be possible to make the former syntax work though?
No, PROGMEM (same for __flash et al.) only work for data in static
storage. That's because sections are used to locate such data. Data of
automatic storage duration like in your 1st example lives on the stack.
Note that your 2nd example will not work with automatic data because its
lifetime ends at the end of the enclosing block, hence using its address
after the end of the block is undefined behaviour (using a dangling
reference to a declined local).
Johann