avr-gcc-list
[Top][All Lists]
Advanced

[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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]