Arduino IDE: как получить длину PROGMEM const?

Я определил массив байтов как константу во флэш-памяти Atmel:

const uint8_t eye [] PROGMEM = {
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};

Как я могу (повторно) прочитать длину этой константы в программе? Все доступные функции в avr/pgmspace.h не обеспечивают нужной длины, независимо от того, как я их использую. Я попробовал strlen (глаз), strlen_P (глаз), strLen_PF (глаз), а также sizeof (глаз). Я новичок в C, поэтому я не уверен во всем, что касается указателей.

, 👍0

Обсуждение

вы уже знаете длину... это 16 байт, @jsotola

@jsotola Действительно, но я хочу прочитать длину массива в функции, которая получает массив в качестве параметра., @needfulthing

sizeof(), при наличии указателя на константу (или указателя на что-либо еще в этом отношении), который у вас есть, когда вы передаете его функции, дает вам размер этого указателя. На 8-битном Arduino это всегда будет 2. strlen() работает только со строками - массивами с завершающим нулем, а это не так., @Majenko

Размер 2 - это именно то, что я получил в функции. Разве нет способа получить размер массива, когда у вас есть только адрес указателя на массив?, @needfulthing

Нет. Вы можете определить такие вещи только во время компиляции (sizeof — это оператор, а не функция). Установка константы или создание макроса #define, содержащего размер, рассчитанный во время компиляции (как в ответе C_Elegans), - это способ сделать это., @Majenko


1 ответ


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

3

Вероятно, лучше всего было бы определить под ним

const int eye_len = sizeof(eye)/sizeof(eye[0]);

Если компоновщик выполняет оптимизацию времени компоновки или если вы используете его только в одном и том же файле (и объявляете его статическим), это не должно занимать памяти, иначе оно займет два байта оперативной памяти.

,

Это работает, хотя я не знаю, как. Думаю, мне нужно больше читать о C., @needfulthing

Sizeof(array) дает размер всего массива в байтах, а sizeof(array[0]) дает размер в байтах одного элемента в массиве. Разделите первое на второе, и вы получите количество элементов в вашем массиве. В этом случае вы могли бы обойтись без второго sizeof, но он все еще работает, даже если вы измените тип данных в массиве., @C_Elegans

@BeB00 может быть из-за того, что он использовал sizeof(eye) в другом файле, и это дало ему размер указателя, @C_Elegans

Это звучит вполне логично. Я многое запутал, используя функции длины для строк в массиве байтов (которые рассчитывались из-за отсутствия нулевого завершения) и получая длину указателя вместо длины массива. Это то, что вы получаете, когда чувствуете себя слишком комфортно на языках высокого уровня... :), @needfulthing

Обновление: я нашел другое решение для своих небольших массивов и поместил размер в первый байт массива, в примере я прочитал глаз [0] и перебрал остальные. Таким образом, массивы сохраняют информацию о своем размере, и мне не нужно полагаться на внешние переменные, содержащие значение :), @needfulthing

Обновление 2: я объединил это с самым простым алгоритмом сжатия, который содержит число в байте n (равное 1...x) и значение в байте n+1, поэтому я получаю const uint8_t глаз [] PROGMEM = { 0x03,0x10,0xff };, @needfulthing