Доступ к двумерному массиву во внутреннем цикле PROGMEM

Я не могу получить доступ к элементам 2D-массива PROGMEM из цикла. См. следующий пример:

const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

void setup() {
  Serial.begin(9600);

  Serial.println(pgm_read_byte(&(arr[0][0])));
  Serial.println(pgm_read_byte(&(arr[1][0])));
  Serial.println(pgm_read_byte(&(arr[2][0])));
  Serial.println(pgm_read_byte(&(arr[3][0])));
  for (int i = 0; i < 4; i++) {
    Serial.print(i);
    Serial.print(":");
    Serial.println(pgm_read_byte(&(arr[i][0])));
  }
  int j = 0;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 1;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 2;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 3;
  Serial.println(pgm_read_byte(&(arr[j][0])));
}

void loop() {

}

Выход:

97
101
106
114
0:12
1:174
2:12
3:148
97
101
106
114

Я много раз проверял и перепроверял синтаксис. не смог найти никого, кто столкнулся бы с подобной проблемой. Я не понимаю, почему он не печатает правильные значения внутри цикла. Есть идеи?

РЕДАКТИРОВАТЬ: ожидаемый результат:

97
101
106
114
0:97
1:101
2:106
3:114
97
101
106
114

, 👍0

Обсуждение

использование констант типа arr[1][0] заменяется во время компиляции значением элемента. они не считываются из массива во время выполнения. даже если j имеет постоянное значение, компилятор оценивает его во время компиляции и заменяет значением, @Juraj

Я думаю, вы правы... есть ли способ получить доступ к элементам изнутри цикла?, @arun

https://www.arduino.cc/reference/en/language/variables/utilities/progmem/, @Juraj

Я уже прошел через это... после того, как вы разместили это здесь, я взял несколько идей и заставил их работать... привожу ответ ниже... спасибо..., @arun

@Юрай, извини, думаю, у меня нет возможности проголосовать за тебя, так как я здесь новенький.., @arun

Вы можете сделать это проще. Например, когда каждый массив представляет собой строку с нулевым завершением, или когда все массивы имеют одинаковый фиксированный размер, или когда одна длинная строка с маркерами. Двумерный массив с разным количеством элементов без знания того, сколько элементов допустимо, это кажется очень странным., @Jot


2 ответа


Лучший ответ:

0
const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

void setup() {
  Serial.begin(115200);

  for (int i = 0; i < 4; i++) {
    Serial.print(i);
    Serial.print(':');
    for (int j = 0; j < 4; j++) {
      Serial.print((char) pgm_read_byte_near(pgm_read_word(arr + i) + j));
      Serial.print(',');
    }
    Serial.println();
  }
}

void loop() {

}

выход

0:a,b,c,d,
1:e,f,g,h,
2:j,k,l,m,
3:r,s,t,u,

во время выполнения размер массивов неизвестен, поэтому я печатаю первые 4 элемента

,

1

Пройдя еще раз по ссылке, данной Юрайем выше, я смог заставить ее работать следующим образом:

const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

void setup() {
  Serial.begin(74880);

  Serial.println(pgm_read_byte(&(arr[0][0])));
  Serial.println(pgm_read_byte(&(arr[1][0])));
  Serial.println(pgm_read_byte(&(arr[2][0])));
  Serial.println(pgm_read_byte(&(arr[3][0])));
  for (int i = 0; i < 4; i++) {
    Serial.print(i);
    Serial.print(":");
    Serial.println(pgm_read_byte_near(pgm_read_word(&(arr[i])) + 0));
  }
  int j = 0;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 1;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 2;
  Serial.println(pgm_read_byte(&(arr[j][0])));
  j = 3;
  Serial.println(pgm_read_byte(&(arr[j][0])));
}

void loop() {

}

Теперь он показывает ожидаемый результат, и возможен доступ из внутреннего цикла с использованием индекса переменной. Спасибо.

,