Storing a struct with bitfields in PROGMEM

How would one go about storing a struct array with bitfields in PROGMEM? Printing means works, but I have problems with ci_vals.

#include <avr/pgmspace.h>
#include <Arduino.h>

struct ui16s {

    uint16_t ui:16;
    uint8_t scale:7;
    uint8_t sign:1;

};

const uint8_t length = 6;

const uint16_t means[] PROGMEM = {
    10, 20, 32, 29, 37, 28
};

const struct ui16s ci_vals[] PROGMEM = {
    {10, 2, 0b0}, {20, 4, 0b1}, {32, 2, 0b1}, 
    {11, 1, 0b0}, {15, 0, 0b1}, {24, 0, 0b0}
};

void setup() {

    Serial.begin(9600);

    delay(1000);

    uint8_t i = 0;
    for (; i < length; ++i) {


        Serial.println(pgm_read_word(ci_vals + i));                     //printing ui
        Serial.println(pgm_read_byte((ci_vals + i) -> scale));      //printing "garbage" (always 12)
                                                                                        //I have no idea how to access the last byte of each struct
                                                                                        // i hoped "-> scale" would offset the addres with 16bit
    }

}

void loop() {

}

The arrays in my projects are bigger than 6. Each 200ms I need 1 time acces to means and ci_vals.

uint16_t arr[length];
struct ui16s temp[length];
uint32_t sum = 0;

for (i = 0..length)
     temp[i] = fct_sub(arr[i], pgm_read_word(means + i)); //arr[i] - means[i]

struct ui16s uitemp;
for (i= 0..length) {
    uitemp = fct_extract(ci_vals[i]);
    sum += fct_mult(temp[i], uitemp);
}


// fct_extract probably along these lines
fct_extract(addr) {
   ui = pgm_read_word(addr);
   scale = ??
   sign = ??
}

So how do I get access to the last byte?

This seemed a solution, c - Clarification of use of structs with Arduino and storing structs in PROGMEM - Stack Overflow
But I don’t understand the for loop.

I also looked at avr/pgmspace.h. read_word and read_byte are macros for resp. LPM_word_enhanced and LPM_enhanced. Which was interesting, and semi chinese. They both accept a 16bit address and the read_word has more instructions, I guess it has to to with reading MSB and LSB.
If I can offset the address with 16bits I should be able to use read_byte no?

The ui16s is already a typedef.
You can do

const ui16s ci_vals[] PROGMEM = {

The pgm functions can read a byte and word, not a bitfield ! That would require a whole new set of functions.
Why not do the most obvious thing: create such a struct in RAM and use memcpy_P to copy one item of the array from progmem. Then you can extract your bitfield from the data in RAM and that will be solved by the compiler as it normally does.

Because I didn't know that existed. Thanks, will try tomorrow

@Speklap, do not hijack. Thread split.

Original question was answered and I came on that thread by googling. Figured I might aswell ask it here to not make useless threads. Guess moderation here is different than I’m used too.

Anyways, memcpy_P did the trick. For future visitors, this code works.

#include <avr/pgmspace.h>
#include <Arduino.h>

struct ui16s {

    uint16_t ui:16;
    uint8_t scale:7;
    uint8_t sign:1;

};

const uint8_t length = 6;

const uint16_t means[] PROGMEM = {
    10, 20, 32, 29, 37, 28
};

const struct ui16s ci_vals[] PROGMEM = {
    {10, 2, 0b0}, {20, 4, 0b1}, {32, 2, 0b1}, 
    {11, 1, 0b0}, {15, 0, 0b1}, {24, 0, 0b0}
};

void setup() {

    Serial.begin(9600);

    delay(1000);

    uint8_t i = 0;
    for (; i < length; ++i) {

    	struct ui16s val;
    	memcpy_P(&val, ci_vals + i, sizeof(struct ui16s));

        Serial.println(pgm_read_word(means + i));
        Serial.print(val.sign ? "-" : "");
        Serial.print(val.ui);
        Serial.print(" / 2 ^ ");
        Serial.println(val.scale);
        Serial.println();

    }

}

void loop() {

}

You don’t have to use those includes. The Arduino already includes them.
If you don’t use the Arduino IDE, can you write that as comment in the top of the sketch ?
The struct is already a typedef. Once you have the type ‘ui16s’, then you don’t need the keyword ‘struct’.
When using the pointer to an element of an array, I prefer to stay close to the PROGMEM documentation en PROGMEM tutorial by Nick Gammon and use: & ( ci_vals [ i ] )
I think it is okay to assign the number 0 or 1 to a bitfield of only 1 bit.

That results into this:

struct ui16s {
  uint16_t ui:16;
  uint8_t scale:7;
  uint8_t sign:1;
};

const uint8_t length = 6;

const uint16_t means[] PROGMEM = {
  10, 20, 32, 29, 37, 28
};

const ui16s ci_vals[] PROGMEM = {
  {10, 2, 0}, 
  {20, 4, 1}, 
  {32, 2, 1},
  {11, 1, 0}, 
  {15, 0, 1}, 
  {24, 0, 0}
};

void setup() {

  Serial.begin(9600);

  for (uint8_t i = 0; i < length; ++i) {

    ui16s val;
    memcpy_P(&val, &(ci_vals[i]), sizeof(ui16s));

    Serial.println(pgm_read_word(&(means[i])));
    Serial.print(val.sign ? "-" : "");
    Serial.print(val.ui);
    Serial.print(" / 2 ^ ");
    Serial.println(val.scale);
    Serial.println();
  }
}

void loop() {
}